c – 操作符<< on模板参数类型成员只会在clang中导致错误

前端之家收集整理的这篇文章主要介绍了c – 操作符<< on模板参数类型成员只会在clang中导致错误前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有这个例子:
#include <iostream>
#include <tuple>
#include <string>

template <typename T>
class A {
public:
    A(const T &t) : m_t(t) {}
    void foo() {
        std::cout << m_t << std::endl;
    }

private:
    T m_t;
};

typedef std::tuple<std::string,std::string> Type;
std::ostream &operator<<(std::ostream &os,const Type &t) {
    os << std::get<0>(t) << " " << std::get<1>(t);
    return os;
}

int main() {
    A<Type> a(Type{"ala"," ma kota"});
    a.foo();
    return 0;
}

与cl(3.6)产生:

test_clang.cpp:10:19: error: call to function 'operator<<' that is neither visible in the template definition nor found by argument-dependent lookup
        std::cout << m_t << std::endl;
              ^
test_clang.cpp:26:7: note: in instantiation of member function 'A<std::tuple<std::basic_string<char>,std::basic_string<char> > >::foo' requested here
    a.foo();
      ^
test_clang.cpp:19:15: note: 'operator<<' should be declared prior to the call site
std::ostream &operator<<(std::ostream &os,const Type &t) {

在g -4.8与C 11和g -5.2.1与C 17建立没有错误发生. cl -3.6需要在A :: foo< T>之前定义std :: ostream& operator<(std :: ostream& os,const Type& t). 从我的角度看,成员m_t取决于模板参数类型,并使用运算符<<在模板定义期间不需要这种类型.为什么cl声有编译错误

解决方法

std::tuple<std::string,std::string>

我们来看看这个类型的关联命名空间. [basic.lookup.argdep] /(2.2):

Its associated namespaces are the
innermost enclosing namespaces of its associated classes.

这将是命名空间标准或辅助命名空间,但肯定不是全局命名空间.

Furthermore,if T is a class template specialization,its associated
namespaces and classes also include: the namespaces and classes
associated with the types of the template arguments provided for
template type parameters (excluding template template parameters); [… inapplicable rules…]

递归地将上述应用到std :: string为相关联的命名空间提供命名空间std(以及辅助的).当然不是全局命名空间.显然,对于std :: cout可以重复相同的论证,得出相同的结论.

因此,ADL将不会查看全局命名空间,这正是您的重载被声明的地方.

最后,根据[temp.dep.candidate] / 1,名称解析失败:

GCC在这里表现不一致见#51577.

猜你在找的C&C++相关文章