c – 模板中的朋友功能(为什么这在Visual Studio中失败但在GCC和
鉴于以下内容(剥离和设计以突出问题):
#include <utility> namespace Generic { class Whatever { public: // ISSUE1 (member "swap()" has same name as non-member template) void swap() { } }; // Forward declaration of class template "Test" template <class> class Test; // Prototype of function template "swap()" for class template "Test" template<class T> void swap(Test<T> &,Test<T> &); ///////////////////////////////////////////////////////////////// // Class template "Test" ///////////////////////////////////////////////////////////////// template <class T> class Test : public T { public: // Default constructor Test() = default; // Move constructor Test(Test &&test) : BaseClass(std::move(test)) { } // Assignment operator Test& operator=(Test test) { // Note that the "Generic:" prefix here has no impact on the results Generic::swap(*this,test); return (*this); } private: using BaseClass = T; // ISSUE2 (qualified call - prefixing with "Generic:") friend void Generic::swap<T>(Test &,Test &); }; ///////////////////////////////////////////////////////////////// // Canonical swap function for class "Test" just above ///////////////////////////////////////////////////////////////// template<class T> void swap(Test<T> &,Test<T> &) { } } // namespace Generic int main() { using namespace Generic; Test<Whatever> test1; Test<Whatever> test2; test2 = std::move(test1); return 0; } 任何人都可以看到它不应该编译的任何理由.请注意注释中的ISSUE1和ISSUE2.这些会影响结果. ISSUE1和ISSUE2有4种组合可以让事情发挥作用(见下表),虽然我知道另一种纠正方法,但这4种组合是我想要关注的.请注意,所有4种组合都在GCC和Clang中完全编译,但只有第4项在Visual Studio 2017(最新版本)中干净地编译.其他组合(1到3)失败,并在下面的RESULT列中看到错误(编译器引用了所有3种情况下ISSUE2行的问题): ISSUE1 ISSUE2 RESULT ------ ------ ------ 1) Leave unchanged Leave unchanged 'Generic::Test': use of class template requires template argument list 'Generic::swap': not a function 2) Leave unchanged Remove "Generic:" qualifier syntax error: missing ';' before '<' 'swap': illegal use of type 'void' 'Generic::swap': 'friend' not permitted on data declarations 'Generic::swap': redefinition; previous definition was 'function' unexpected token(s) preceding ';' 3) Comment out member "swap()" Leave unchanged 'Generic::Test': use of class template requires template argument list 'Generic::swap': not a function 4) Comment out member "swap()" Remove "Generic:" qualifier Works!!! 是Visual Studio只是错误或GCC和Clang错了(前者似乎是基于我对合格/非限定名称查找规则,ADL等的理解).谢谢. 解决方法
嘿,找到了博客:
Two-phase name lookup support comes to MSVC. 一些相关的摘录:
然后,文章继续发布一些与n.m.’s minimal example非常相似的代码.
最后,关于使MSVC使用更新的两阶段模板解析的注释:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |