C++ std::make#u共享三值返回';不编译

C++ std::make#u共享三值返回';不编译,c++,visual-studio-2010,factory,ternary-operator,C++,Visual Studio 2010,Factory,Ternary Operator,我正在使用VisualStudio2010并使用factory创建抽象基类的两个实现之一。factory Create方法接受bool标志,并在共享的\u ptr中返回两个impl中的一个。使用if语句对我来说很好,但是当我尝试使用带有make_共享调用的三元语句时,编译器会抱怨 class Base { public: Base() {}; }; class Foo : public Base { public: Foo() {}; }; class Bar : public

我正在使用VisualStudio2010并使用factory创建抽象基类的两个实现之一。factory Create方法接受bool标志,并在共享的\u ptr中返回两个impl中的一个。使用if语句对我来说很好,但是当我尝试使用带有make_共享调用的三元语句时,编译器会抱怨

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;
}
类基{
公众:
Base(){};
};
Foo类:公共基础{
公众:
Foo(){};
};
分类栏:公共基础{
公众:
Bar(){};
};
阶级工厂{
公众:
静态标准::共享ptr创建(bool-isFoo){
返回isFoo?
std::使_共享():
std::使_共享();
}
};
int main(){
std::shared_ptr instance=Factory::Create(true);
返回0;
}
VS给出的错误是 '没有可执行此转换的用户定义的转换运算符,或者无法调用该运算符 c:\path\file.h(78):错误C2668:“std::tr1::shared\u ptr::shared\u ptr”:对重载函数的调用不明确 具有 [ _Ty=基础 ]

注意

static std::shared_ptr<Base> Create(bool isFoo) {
    if (isFoo)
        return std::make_shared<Foo>();
    return std::make_shared<Bar>();
}
static std::shared_ptr Create(bool-isFoo){
if(isFoo)
返回std::make_shared();
返回std::make_shared();
}

编译得很好。

这是因为三元运算中的第二个和第三个表达式必须相互转换。在您的情况下,
std::shared_ptr
不能转换为
std::shared_ptr
,反之亦然


虽然它们都可以转换为
std::shared_ptr
,但它们不能相互转换。

std::make_shared()的返回类型为
std::shared_ptr


两个derived都可转换为它们的基类,因此两个
共享的ptr
s都可以转换为
共享的ptr
,但三元运算符希望其第二个和第三个参数已经具有相同的类型,或者,正好其中一个可以转换为另一个。

当三值条件运算符的第二个和第三个操作数有两种不同的类类型时,通常必须能够将其中一个转换为另一个。如果两者都不能转换为另一种,则程序将无法编译,即使存在第三种类型,这两种类型都可以转换为,如本例所示

解决方案:

return isFoo ?
    std::shared_ptr<Base>(std::make_shared<Foo>()) :
    std::shared_ptr<Base>(std::make_shared<Bar>());
返回isFoo?
std::shared_ptr(std::make_shared()):
std::shared_ptr(std::make_shared());

正如您的注释所示,问题在于三元运算符。每个表达式(甚至像A=1的类)都有C++的类型。在您的示例中,编译器必须尝试推导表达式
isFoo?std::make_shared():std::make_shared()通常编译器会查找对第二个和第三个操作数都有效的类型(本例中的make_共享调用)。VS试图在其错误消息中告诉您的是,它找不到公共类型

相反,if语句之所以有效,是因为make_共享调用是两个独立的表达式,因此不需要公共类型