`a?b:c`的操作数可以有不同的类型吗?最好的选择是什么?
#include <iostream>
#include <string>
struct Base
{
Base(int)
{
std::cout << "intn";
}
Base(std::string)
{
std::cout << "stringn";
}
};
struct S : Base
{
S(bool b)
: Base{ b ? int{} : std::string{} }
{}
};
int main()
{
S(42);
S("fortytwo");
}
这段代码有几个编译错误,但更有趣的是
?: 的操作数有不同的类型:int 和 std::string。
约束:
Basector 初始化常量,所以我不能使用 ctor 主体。- 这是唯一一个具有
bool魔力的派生类,因此更改Base以适应它是......不可取的。
现在怎么办?这段代码的重点是派生类S调用Base基于 a的重载构造函数之一bool。
考虑的解决方案:
- 一个IIFE能够工作,但相当难看且长。
- 辅助函数 - 相同。
- 模板 S 并传递到
b那里 - 我需要一个运行时决定。
编辑:@Yakk - Adam Nevraumont的回答对原始问题来说非常棒。
但我错过了一个关键的细节。Base是抽象的,即添加virtual void foo() = 0;到它的定义中。所以它不能被实例化。
回答
S(bool b):
Base{ b ? Base{int{}} : Base{std::string{}} }
{}
活生生的例子。
你可以变得更狂热:
S(bool b):
Base{ [&]()->Base{
if (b)
return int{};
else
return std::string{};
}() }
{}
活生生的例子。
在第一个示例中,移动完成;在第二种情况下,保证省略意味着只Base创建一个对象。您可以通过添加以下内容来测试:
Base(Base&&)=delete;