我使用Visual Studio 2010并拥有工厂来创建抽象基类的两个实现之一。工厂Create方法接受bool标志并返回shared_ptr中的两个impl之一。使用if语句对我来说很好,但是当我尝试使用带有make_shared调用的三元组时,编译器会抱怨。
class Base {
public:
Base() {};
};
class Foo : public Base {
public:
Foo() {};
};
class Bar : public Base {
public:
Bar() {};
};
class Factory {
public:
static std::shared_ptr<Base> Create(bool isFoo) {
return isFoo ?
std::make_shared<Foo>() :
std::make_shared<Bar>();
}
};
int main() {
std::shared_ptr<Base> instance = Factory::Create(true);
return 0;
}
VS给出的错误是 &#39;没有可用于执行此转换的用户定义转换运算符,或者无法调用运算符 c:\ path \ file.h(78):错误C2668:&#39; std :: tr1 :: shared_ptr&lt; _Ty&gt; :: shared_ptr&#39; :模糊调用重载函数 同 [ _Ty =基 ]
请注意
static std::shared_ptr<Base> Create(bool isFoo) {
if (isFoo)
return std::make_shared<Foo>();
return std::make_shared<Bar>();
}
编译得很好。
答案 0 :(得分:6)
这是因为三元操作中的第二个和第三个表达式必须可以相互转换。在您的情况下,std::shared_ptr<Foo>
根本无法转换为std::shared_ptr<Bar>
,反之亦然。
虽然它们都可以转换为std::shared_ptr<Base>
,但它们不能相互转换。
答案 1 :(得分:3)
当您有两个不同的类类型作为三元条件运算符的第二个和第三个操作数时,通常必须可以将其中一个转换为另一个。如果两者都不能转换为另一个,则程序不会编译,即使第三种类型都可以转换为,在这种情况下也是如此。
解决方案:
return isFoo ?
std::shared_ptr<Base>(std::make_shared<Foo>()) :
std::shared_ptr<Base>(std::make_shared<Bar>());
答案 2 :(得分:1)
std::make_shared<T>()
的返回类型为std::shared_ptr<T>
。
两个派生都可以转换为它们的基类,因此两个shared_ptr
都可以转换为shared_ptr<base>
,但是三元运算符期望它的第二个和第三个参数已经 相同类型,或其中一个可转换到另一个。
答案 3 :(得分:0)
正如您的注释似乎表明的那样,问题在于三元运算符。每个表达式(甚至像a = 1这样的东西)都有一个c ++类型。在您的示例中,编译器必须尝试推导表达式isFoo ? std::make_shared<Foo>() : std::make_shared<Bar>();
的类型。通常,编译器会查找适用于第二个和第三个操作数的类型(在本例中为make_shared调用)。 VS在其错误消息中试图告诉您的是它找不到常见类型。
相反,if语句有效,因为make_shared调用是两个独立的表达式,因此不需要常用类型。