尝试将std :: make_unique声明为模板化类的朋友时,MSVC出错

时间:2015-11-24 23:25:32

标签: c++ c++14 unique-ptr friend-function msvc12

显然今天,MSVC正在尽力说服我切换到铿锵声。但我不会放弃。我早些时候曾问过this question想知道如何将std::make_unique声明为我班级的friend

我在我的简单场景中得到了一个非常好的答案,当我在wandbox上使用clang尝试它时,它编译得很好。

所以我很高兴回到Visual Studio 2013继续编码。我的代码的一部分是:

// other includes
#include <string>
#include <memory>

template <typename Loader, typename Painter, typename MeshT>
class Model
{
public:
    friend std::unique_ptr<Model> std::make_unique<Model>(
        const std::string&,
        const std::shared_ptr<Loader>&,
        const std::shared_ptr<Painter>&);

    // Named constructor
    static std::unique_ptr<Model> CreateModel(
        const std::string& filepath,
        const std::shared_ptr<Loader>& loader,
        const std::shared_ptr<Painter>& painter)
    {
        // In case of error longer than the Lord of the Rings trilogy, use the
        // line below instead of std::make_unique
        //return std::unique_ptr<Model>(new Model(filepath, loader, painter));
        return std::make_unique<Model>(filepath, loader, painter);
    }

// ...
protected:
    // Constructor
    Model(
        const std::string& filepath,
        const std::shared_ptr<Loader>& loader,
        const std::shared_ptr<Painter>& painter)
        : mFilepath(filepath)
        , mLoader(loader)
        , mPainter(painter)
    {
    }

// ...

};

好吧,说实话,我没想到第一次就把它弄好了,但我确信我能从错误信息中找出一些意义:

1>d:\code\c++\projects\active\elesword\src\Model/Model.hpp(28): error C2063: 'std::make_unique' : not a function
1>          ..\..\src\Main.cpp(151) : see reference to class template instantiation 'Model<AssimpLoader,AssimpPainter,AssimpMesh>' being compiled

显然,MSVC并不认为std::make_unique 功能是......等功能。

最糟糕的是,我累了,我觉得我错过了一些非常非常明显的东西。任何人都可以帮我解开吗?

此外,任何人都可以尝试使用Visual Studio 2015吗?只是出于好奇..

注意:我知道我可以(可能应该)只使用return std::unique_ptr<Model>(new Model(filepath, loader, painter));,但感觉不对。

1 个答案:

答案 0 :(得分:7)

尝试使用std函数会让你陷入危险的境地,因为你对它们的实现做出了一些假设并不受标准保证的假设。例如,您希望std :: make_unique成为朋友,以便它可以访问受保护的构造函数,但是如果std :: make_unique的实现将其委托给其他一些秘密函数怎么办?你需要的是与秘密功能交朋友,但这是秘密,所以你不能。

其他并发症:某些形式的std :: make_unique并没有完全由标准规定(尽管我认为这并不适用于这个确切的例子)。在编译器完全支持可变参数模板之前,VC ++的旧版本使用宏魔术来模拟可变参数模板,因此虽然存在std :: make_unqiue,但它可能没有您期望的实际签名。