ADL 找不到重载函数
ADL cannot find overloaded function
template<typename T>
struct S
{
bool valid(T a)
{ return is_valid(a); }
};
bool is_valid(int)
{ return true; }
int main()
{
S<int> s;
s.valid(0);
}
VS 编译此示例很好,而 GCC 说:
错误:"is_valid"未在此范围内声明,并且没有声明 在实例化点通过依赖于参数的查找找到 [-允许]
我不确定为什么 ADL 找不到bool is_valid(int)
,因为它在S<int> s
实例化之前定义。我想这是正确的行为,因为Clang也说了同样的话。所以我试图添加
template<typename T>
bool is_valid(T);
一开始使用函数重载,现在Godbolt通过Clang或GCC编译它,而不是本地GCC编译或Ideone。
在这种情况下,如何使用 ADL 在模板声明 (GCC( 后提供函数定义?奖励:为什么 Godbolt 编译最后一个样本?
溶液:
多亏了公认的答案,我发现问题在于 ADL 专门处理基元类型。这帮助我最终得到了以下解决方案,该解决方案使用模板化函数的前向声明,该函数可以重载用户定义的类型或专门用于基元类型。
template<typename T>
bool is_valid(T);
template<typename T>
struct S
{
bool valid(T a)
{ return is_valid(a); }
};
template<>
bool is_valid<int>(int)
{ return true; }
struct User_data
{};
bool is_valid(User_data)
{ return true; }
int main()
{
S<int> s_primitive;
s_primitive.valid(0);
S<User_data> s_user_data;
s_user_data.valid(User_data{});
}
魔杖盒
解决方案是转发声明is_valid(int)
:
bool is_valid(int);
template<typename T>
struct S
{
bool valid(T a)
{ return is_valid(a); }
};
基本类型(如int
(的ADL生成一组空的命名空间和类来考虑,因此当您将0
传递到S::valid
时,您不会引入外部is_valid(int)
。前向声明有效地让模板知道函数的存在。
关于你在Godbolt中看到的行为...编译器资源管理器必须完成一些额外的工作,因为据称它使用的相同 gcc 和 clang 版本不适用于任何其他编译器(如 Wandbox(
如果你真的希望 ADL 工作,那么你需要修改自由函数is_valid
以便 ADL 是一个选项。我的建议是声明一个与所有自由浮动is_valid
函数ADL_Helper
相同范围的帮助程序结构,然后S::is_valid
将传递一个实例:
struct ADL_Helper{};
template<typename T>
struct S
{
bool valid(T a)
{ return is_valid(a, ADL_Helper{}); }
};
bool is_valid(int, ADL_Helper)
{ return true; }
int main()
{
S<int> s;
s.valid(0);
}
演示
相关文章:
- 为什么使用SFINAE而不是函数重载
- 为什么我不能在 C++ 中的特定函数重载中调用同一函数的任何其他重载?
- c++:可变模板和函数重载
- 在缺少函数重载时抛出异常,并带有 std::variant 而不是编译时错误
- 解决模板成员函数重载
- 为什么不允许成员函数和非成员函数之间的函数重载?
- 推断模板化函数中的函数重载
- C++复制函数重载导致"must be a nonstatic member function"错误
- 为什么 std::sort 找不到合适的(静态成员)函数重载?
- 可变参数泛型 lambda 和函数重载
- C++中的函数重载和继承
- 当有右值构造函数可用时,为什么从右值调用类引用构造函数重载?
- C/C++ 可变参数宏函数重载
- 将基类的成员函数重载到其他派生类C++
- C++ 函数重载匹配
- C++函数重载,具体步骤是什么
- C++:使用 param pack 显式调用函数重载
- 隐式生成的函数重载用于右值参数?
- 使用函数重载输入运算符
- 运算符重载函数上的函数重载