如何让编译器选择非成员函数重载
How to make compiler choose a non-member function overload
我正在编写一个库,它对内置类型(int、float、double 等)和用户提供的类型执行一些操作。其中之一由模板函数执行:
namespace lib
{
template<typename T>
inline auto from_string(std::string const & s, T & t) -> bool
{
std::istringstream iss(s);
iss >> t;
return !iss.fail();
}
}
这是一个自定义点 - 用户可以为他们的类型重载此函数:
namespace foo
{
class UserType
{
// (...)
};
}
namespace lib
{
inline auto from_string(std::string const & s, foo::UserType & ut) -> bool
{
// some implementation
}
}
或在同一命名空间中具有 from_string
函数并可通过 ADL 访问:
namespace foo
{
inline auto from_string(std:string const & s, UserType & ut) -> bool
{
// some implementation
}
}
}
现在,除了字符串到类型的转换,该库还执行类型到字符串、比较和更多操作。我想通过 类 系列完成它,该系列将值作为 std::any
:
的实例保存
namespace lib
{
class TypeHandler
{
public:
virtual TypeHandler() = default;
virtual auto from_string(std::string const & string, std::any & value) const -> bool = 0;
// more functions
};
template<typename T>
class TypeHandlerT : public TypeHandler
{
public:
auto from_string(std::string const & string, std::any & value) const -> bool override
{
T val;
if (from_string(string, val)) // an attempt to call the free function
{
value = val;
return true;
}
return false;
}
}
}
我想使用 TypeHandlerT
类 为了方便。
但是,使用这样的代码,当我尝试使用 TypeHandlerT<int>
:
时出现以下编译器错误
error C2664: 'bool lib::TypeHandlerT<T>::from_string(const std::string &,std::any &) const':
cannot convert argument 2 from 'T' to 'std::any &' with [ T=int ]
好像from_string
会员版隐藏了免费功能版
有没有办法优雅地解决这个问题?例如,通过将自由功能纳入范围(但如何在不排除 ADL 的情况下做到这一点?)?
我知道一个简单的解决方法是重命名成员函数或自由函数,但我想避免这种情况。
从 TestHandlerT<T>::from_string
的主体开始的基于范围的查找在命中 lib::from_string
之前命中成员函数。所以只需将 lib::from_string
重新引入 using
的 body 范围即可。这也会重新启用 ADL,因为当基于范围的查找命中 class 成员时,ADL 会被抑制。
template<typename T>
struct TypeHandlerT : TypeHandler {
bool from_string(std::string const &string, std::any &value) const -> override {
using lib::from_string;
T val;
if (from_string(string, val)) {
value = val;
return true;
}
return false;
}
};
我正在编写一个库,它对内置类型(int、float、double 等)和用户提供的类型执行一些操作。其中之一由模板函数执行:
namespace lib
{
template<typename T>
inline auto from_string(std::string const & s, T & t) -> bool
{
std::istringstream iss(s);
iss >> t;
return !iss.fail();
}
}
这是一个自定义点 - 用户可以为他们的类型重载此函数:
namespace foo
{
class UserType
{
// (...)
};
}
namespace lib
{
inline auto from_string(std::string const & s, foo::UserType & ut) -> bool
{
// some implementation
}
}
或在同一命名空间中具有 from_string
函数并可通过 ADL 访问:
namespace foo
{
inline auto from_string(std:string const & s, UserType & ut) -> bool
{
// some implementation
}
}
}
现在,除了字符串到类型的转换,该库还执行类型到字符串、比较和更多操作。我想通过 类 系列完成它,该系列将值作为 std::any
:
namespace lib
{
class TypeHandler
{
public:
virtual TypeHandler() = default;
virtual auto from_string(std::string const & string, std::any & value) const -> bool = 0;
// more functions
};
template<typename T>
class TypeHandlerT : public TypeHandler
{
public:
auto from_string(std::string const & string, std::any & value) const -> bool override
{
T val;
if (from_string(string, val)) // an attempt to call the free function
{
value = val;
return true;
}
return false;
}
}
}
我想使用 TypeHandlerT
类 为了方便。
但是,使用这样的代码,当我尝试使用 TypeHandlerT<int>
:
error C2664: 'bool lib::TypeHandlerT<T>::from_string(const std::string &,std::any &) const':
cannot convert argument 2 from 'T' to 'std::any &' with [ T=int ]
好像from_string
会员版隐藏了免费功能版
有没有办法优雅地解决这个问题?例如,通过将自由功能纳入范围(但如何在不排除 ADL 的情况下做到这一点?)?
我知道一个简单的解决方法是重命名成员函数或自由函数,但我想避免这种情况。
从 TestHandlerT<T>::from_string
的主体开始的基于范围的查找在命中 lib::from_string
之前命中成员函数。所以只需将 lib::from_string
重新引入 using
的 body 范围即可。这也会重新启用 ADL,因为当基于范围的查找命中 class 成员时,ADL 会被抑制。
template<typename T>
struct TypeHandlerT : TypeHandler {
bool from_string(std::string const &string, std::any &value) const -> override {
using lib::from_string;
T val;
if (from_string(string, val)) {
value = val;
return true;
}
return false;
}
};