没有前向声明的嵌套函数模板实例化在 GCC 上编译但在 clang 上不编译
Nested function template instantiation without forward declaration compiles on GCC but not on clang
以下代码不能在 clang 中编译,但可以在 GCC (godbolt) 中编译:
template <typename K, typename V>
std::ostream& operator<< (std::ostream& o, const std::map<K, V>& map)
{
const char* sep = "{";
for (const auto& x : map)
{
o << sep << "{" << x.first << ", " << x.second << "}";
sep = ", ";
}
return o << "}";
}
template <typename T>
std::ostream& operator<< (std::ostream& o, const std::vector<T>& vec)
{
const char* sep = "{";
for (const auto& x : vec)
{
o << sep << x;
sep = ", ";
}
return o << "}";
}
// Usage
int main()
{
std::map<int, std::vector<int>> t = {{1, {2, 3}}, {4, {5}}};
std::cout << t << std::endl;
return 0;
}
谁说得对?
顺便说一句,我知道它是 UB,但是将两个模板定义放在 namespace std
中也会使代码在 clang 上编译。
代码借自Is it possible to define operator<< for templated types?
铿锵是对的。您应该在 operator<<
对 std::map
的定义之前移动 operator<<
对 std::vector
的声明。
(强调我的)
For a dependent name used in a template definition, the lookup is postponed until the template arguments are known, at which time ADL examines function declarations with external linkage (until C++11)
that are visible from the template definition context as well as in the template instantiation context, while non-ADL lookup only examines function declarations with external linkage (until C++11)
that are visible from the template definition context (in other words, adding a new function declaration after template definition does not make it visible except via ADL).
以下代码不能在 clang 中编译,但可以在 GCC (godbolt) 中编译:
template <typename K, typename V>
std::ostream& operator<< (std::ostream& o, const std::map<K, V>& map)
{
const char* sep = "{";
for (const auto& x : map)
{
o << sep << "{" << x.first << ", " << x.second << "}";
sep = ", ";
}
return o << "}";
}
template <typename T>
std::ostream& operator<< (std::ostream& o, const std::vector<T>& vec)
{
const char* sep = "{";
for (const auto& x : vec)
{
o << sep << x;
sep = ", ";
}
return o << "}";
}
// Usage
int main()
{
std::map<int, std::vector<int>> t = {{1, {2, 3}}, {4, {5}}};
std::cout << t << std::endl;
return 0;
}
谁说得对?
顺便说一句,我知道它是 UB,但是将两个模板定义放在 namespace std
中也会使代码在 clang 上编译。
代码借自Is it possible to define operator<< for templated types?
铿锵是对的。您应该在 operator<<
对 std::map
的定义之前移动 operator<<
对 std::vector
的声明。
(强调我的)
For a dependent name used in a template definition, the lookup is postponed until the template arguments are known, at which time ADL examines function declarations
with external linkage (until C++11)
that are visible from the template definition context as well as in the template instantiation context, while non-ADL lookup only examines function declarationswith external linkage (until C++11)
that are visible from the template definition context (in other words, adding a new function declaration after template definition does not make it visible except via ADL).