MSVC和Clang之间的大括号不一致或初始化行为相等



我在Visual Studio 2013和Clang上编译了以下代码:

#include <memory>
template<typename T>
class foo
{
public:
   typedef void (T::*CallbackFn)();
   foo(T* mem, CallbackFn cb) : m_member(mem), m_cb(cb) {}
private:
   T* m_member;
   CallbackFn m_cb;
};
class another
{
private:
   void callback() {}
public:
   std::unique_ptr<foo<another>> f{new foo<another>(this, &another::callback)};
};
int main() {}

(Coliru上的现场样品)

当在clang和GCC上编译时,此代码运行良好。然而,在VS2013上,它失败了:

main.cpp(22): error C2276: '&' : illegal operation on bound member function expression
main.cpp(22): error C2664: 'foo<another>::foo(const foo<another> &)' : cannot convert argument 1 from 'another *const ' to 'const foo<another> &'
          Reason: cannot convert from 'another *const ' to 'const foo<another>'
          No constructor could take the source type, or constructor overload resolution was ambiguous

由于某种原因,VS编译器试图调用foo的复制构造函数,这根本没有意义。它完全忽略了构造函数的第二个参数。

有趣的是,如果我将foo的构造函数调用更改为大括号,如下所示:

std::unique_ptr<foo<another>> f{new foo<another>{this, &another::callback}};

它在微软风投上运行得很好。有人能解释这种行为吗?一种方式比另一种方式更正确吗?这只是另一个MSVC错误,还是由于一些不受支持的C++11功能?

有人能解释这种行为吗?

一旦编译器遇到第一个错误,剩下的就是垃圾。忽略它。(我通常只看出现的第一个编译器错误,请参阅这里的VC++)

一种方式比另一种方式更正确吗?

在这种情况下,两者完全等同。MSVC简单地未能解析&another::callback,并且随后忽略它以对该行进行进一步分析。

最新更新