Foo(MyStruct x):
Foo(
(x.e==A)?x:MyStruct{0,B},
(x.e==A)?MyStruct{0,A}:x
)
是一种直接的方法。请注意,相同的 ctor 被委派给,但参数发生了变化。这与您的示例一致,但可能不是您真正的问题。
现在,假设您有一个更复杂的问题。您真的希望根据运行时值调用不同的构造函数吗?
如果我们希望根据运行时值调用不同的 ctor,我们可能不得不依赖(希望省略)复制或移动 ctor。
简单的方法就是
Foo(MyStruct x):
Foo( (x.e==A)?
Foo{x, {0,B}}:
Foo{{0,A}, x}
)
{}
我们使用不同的Foo 调用Foo 复制/移动ctor,具体取决于x.e。这有阻塞省略的小问题。
此时您应该停下来。因为下一步很疯狂。
这是避免构造候选 Foos 的一种过于花哨的方法,我认为甚至允许省略(不知道编译器是否真的会这样做):
template<class T>
struct delayed_construct {
void const* data;
T(*func)(void const*);
template<class F>
delayed_construct( F const& f ):
data(&f),
func([](void const* ptr)->T{
F const& f = *static_cast<F const*>(ptr);
return f();
})
{}
T operator()() const {
return func(data);
}
};
struct Foo {
explicit Foo( delayed_construct<Foo> d ):Foo(d()) {}
Foo(MyStruct a, MyStruct b) {}
Foo(MyStruct x):
Foo( (x.e==A)?
delayed_construct<Foo>{[&]()->Foo{
return {x, {0,B}};
}}:
delayed_construct<Foo>{[&]()->Foo{
return {{0,A}, x};
}}
)
{}
};
它做了一堆非常复杂的东西,让你在调用两个不同的ctors之间做出选择。如果您不选择要调用的 ctor,甚至不会评估 ctor 的参数。
delayed_construct<Foo> 基本上是一个std::function<F()>,它假定它的生命周期将是一个临时的,这样做可能会受到编译器稍微更容易的优化。
我相信该标准允许在 Foo(MyStruct x) 中创建的 lambda 中构造的 Foo 直接构造我们从中调用它的 Foo。我可能是错的,而且很有可能即使我是对的,编译器也可能不会这样做。