C++11/14中,std::string的make_unique模板存在歧义重载问题。

9

请问如何解决make_unique的二义性重载警告,错误来自哪里以及它的确切含义是什么(我知道什么是二义性重载,但我不确定为什么在这个特定的代码中会出现这种情况)?我正在使用c++11,因此我使用Herb Sutter推荐的模板。

使用它时,我会得到以下错误:

Error   4   error C2668: 'make_unique' : ambiguous call to overloaded function

在Visual Studio 13中,悬停提示工具会显示以下两种方法:

function template "std::enable_if<!std::is_array<_Ty>::value, std::unique_ptr<_Ty,std::default_delete<_Ty>>>::type std::make_unique<_Ty,_Types...>(_Types &&..._Args)"
function template "std::unique_ptr<T, std::default_delete<T>> make_unique<T,Args...>(Args...)
argument types are: std::string

第二个应该是从make_unique模板中调用的。
/* Will be part of c++14 and is just an oversight in c++11
 * From: http://herbsutter.com/gotw/_102/
 */
template<typename T, typename ...Args>
std::unique_ptr<T> make_unique(Args&& ...args){
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

需要转发的构造函数:

Shader(const std::string& name);

代码产生了错误。
std::string _name = "Shader";
std::unique_ptr<Shader> s = make_unique<Shader>(_name); 
1个回答

5
这个调用含糊不清,因为你确实有std::make_unique,正如你引用的工具提示内容所示。即使你没有写std::,因为你正在传递一个std::string参数相关查找会自动搜索该命名空间

当你说“我正在使用C++11”时,那并不完全正确,因为Visual Studio不允许你选择要编写的标准。它只提供了对任何给定功能的最新支持。显然,Visual Studio 2013拥有C++14的std::make_unique

请删除你的。


很好的发现。但是剩下的问题是为什么VS将两者都视为候选项。OP可能使用了“using namespace std;”?这也是OP应该修复的另一件事情。 - Daniel Frey
1
好的,答案肯定是正确的,因为::make_unique<Shader>(_name)解决了这个问题。还有一个小问题,为什么VS能够看到c++14的方法而不需要给出命名空间。另外一个问题是,如果我只使用c++14的方法,除了需要一个支持c++14的编译器来构建项目之外,还有其他需要注意的事项吗? - Kevin Streicher
进一步思考后,我批准了您的答案,因为我找不到不使用c++14版本的理由,您能想到吗? - Kevin Streicher
@NoxMortem: 不行。你可以将函数的版本放在预处理器的#if块内(如果你能找出用于它的宏),以便你的代码准备好被移植到其他编译器。但除此之外,不行。 - Lightness Races in Orbit
2
@LightnessRacesinOrbit,这是ADL,我认为问题在于当你没有全局范围版本时,编译器不知道make_unique是一个模板名称,因此无法解析<。http://coliru.stacked-crooked.com/a/33fc5b4228e53f63 - T.C.
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接