C++ 编译器找不到重载

C++ 编译器找不到重载,c++,linux,namespaces,c++14,C++,Linux,Namespaces,C++14,我最近正在为我的一些代码处理一些简单类型,并为它们重载插入运算符,以便它们可以轻松打印。我遇到了一个案例,我真的吐了上千行。简化版本如下: #include <iostream> #include <sstream> #include <utility> #include <string> namespace ns{ template<typename KEY, typename VALUE> using KeyValue = std

我最近正在为我的一些代码处理一些简单类型,并为它们重载插入运算符,以便它们可以轻松打印。我遇到了一个案例,我真的吐了上千行。简化版本如下:

#include <iostream>
#include <sstream>
#include <utility>
#include <string>

namespace ns{
template<typename KEY, typename VALUE>
using KeyValue = std::pair<KEY, VALUE>;

template<typename K, typename V>
inline std::ostream& operator<< (std::ostream& os, const KeyValue<K,V>& arg){
  os << "Key: " << arg.first << " Value: " << arg.second;
  return os;
}
}


struct Foo_t{
  double a = 0;
};

inline std::ostream& operator<< (std::ostream& os, const Foo_t& f){
  os << "a: " << f.a;
  return os;
}



int main()
{
  Foo_t foo{6.283185};
  ns::KeyValue<std::string, Foo_t> foo_kv{"Foo_t", foo};

  std::ostringstream oss;
  oss << foo_kv;

  std::cout << oss.str();
}
#包括
#包括
#包括
#包括
名称空间ns{
模板
使用KeyValue=std::pair;
模板

内联std::ostream&operator
KeyValue
std::pair
的别名。定义别名模板的命名空间不被视为ADL的关联命名空间。将只考虑类
std::pair
本身的类和封闭命名空间范围

因此,未找到
ns
内的操作员过载

如果将
Foo\u t
移动到
ns
内部,则会发现此问题,因为ADL会考虑函数参数类型中类型模板参数的类作用域和封闭命名空间作用域

如果
Foo\u t
ns
内,则将
ns
添加到将要搜索的关联作用域列表中,因为它是
Foo\u kv
类类型的类型模板参数。如果在全局命名空间作用域中声明了
Foo\u t
,则只添加全局命名空间作用域(仍由非限定查找搜索)

至于如何修复:如果您希望无论使用何种模板参数都能找到运算符重载,则可以将
KeyValue
设置为一种不同的类型:

template<typename KEY, typename VALUE>
struct KeyValue : std::pair<KEY, VALUE> {
    using std::pair<KEY, VALUE>::pair;
};
模板
结构键值:std::pair{
使用std::pair::pair;
};

或者您可以将运算符重载移动到全局命名空间中。

看起来像是命名空间问题。我可以通过使用ns::operator添加
来解决此问题。请看以下内容: