【问题标题】:Error on MSVC when trying to declare std::make_unique as friend of my templated class尝试将 std::make_unique 声明为我的模板类的朋友时 MSVC 出错
【发布时间】:2016-02-27 14:38:16
【问题描述】:

显然,今天,MSVC 正在尽最大努力说服我改用 clang。但我不会放弃。之前我问过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 函数 是..well..a 函数。

最糟糕的是我累了,我觉得我错过了一些非常非常非常(...)明显的东西。谁能帮我解开?

另外,任何人都可以用 Visual Studio 2015 试试这个吗?只是出于好奇..

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

【问题讨论】:

  • 也不能在 VS2015 上编译,对我来说它看起来像是一个 MSVC 错误。似乎它不会推断模板参数,您需要明确指定它们。因此,如果我创建自己的非可变参数 make_unique,然后将朋友声明更改为 friend std::unique_ptr&lt;A&gt; my::make_unique&lt;A, T&amp;&gt;(T&amp;);,如下例所示,它会在 MSVC 上编译 - coliru.stacked-crooked.com/a/a036bc575b552665
  • 你应该停止尝试与标准库中的某些东西交朋友。那样就是疯狂。
  • Praetorian:嗯,我希望vs2015不会有这个问题。好吧,如果我希望我的项目在所有编译器上工作,我想最好忘记这种方法。顺便说一句,很好的解决方法。我可能会使用它或类似的东西。
  • 一种常见的技术是使用一个公共构造函数,该构造函数需要一个私有标记类型的实例才能调用。

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


【解决方案1】:

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

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

【讨论】:

  • 是的,这绝对有道理。你说的对。感谢您的回答!
猜你喜欢
  • 1970-01-01
  • 2017-02-09
  • 2019-02-06
  • 2016-02-27
  • 2018-09-17
  • 1970-01-01
  • 1970-01-01
  • 2011-03-18
  • 1970-01-01
相关资源
最近更新 更多