C++ 用于泛型类型上泛型操作的SFINAE
我有C++ 用于泛型类型上泛型操作的SFINAE,c++,templates,c++17,sfinae,enable-if,C++,Templates,C++17,Sfinae,Enable If,我有 可以用不同类型(Foo、Bar、int等)构造的类值 类值应该具有常见的操作,如可以替换的 std::ostream &operator<<(std::ostream &os, const Value &value) { // ... } 您可以添加包装以仅强制一次转换: template <typename T> struct OneConversion { OneConversion(const T& t) :
- 可以用不同类型(Foo、Bar、int等)构造的类值
- 类值应该具有常见的操作,如可以替换的
std::ostream &operator<<(std::ostream &os, const Value &value) { // ... }
您可以添加包装以仅强制一次转换:template <typename T> struct OneConversion { OneConversion(const T& t) : t(t) {} operator const T&() const {return t;} const T& t; }; template <typename T> struct isOneConversion : std::false_type {}; template <typename T> struct isOneConversion<OneConversion<T>> : std::true_type {}; struct Value { template<typename T, std::enable_if_t<!isOneConversion<T>::value>* = nullptr> Value(T) {} }; std::ostream &operator<<(std::ostream &os, const Value &value) { auto visitor = [&](auto a) -> decltype(os << OneConversion<decltype(a)>(a)) { return os << OneConversion<decltype(a)>(a); }; // Works visitor(Bar{}); visitor(Foo{}); // Error as expected. return os; }
模板 结构转换 { OneConversion(const T&T):T(T){} 运算符常量T&()常量{return T;} 康斯特T&T; }; 模板 结构isOneConversion:std::false_type{}; 模板 结构isOneConversion:std::true_type{}; 结构值{ 模板*=nullptr> 值(T){} };
std::ostream&operator不修改std::ostream&operator的签名
std::ostream &operator<<(std::ostream &os, const Value &value) { // ... }
template <typename T, typename = std::enable_if_t<std::is_same_v<T, Value>>> std::ostream &operator<<(std::ostream &os, const T &value) { // ... }
... main.cpp:29:12: error: no match for call to '(operator<<(std::ostream&, const T&) [with T = Value; <template-parameter-1-2> = void; std::ostream = std::basic_ostream<char>]::<lambda(auto:1)>) (Foo)' visitor(Foo{}); ~~~~~~~^~~~~~~ ...
template <typename T> struct OneConversion { OneConversion(const T& t) : t(t) {} operator const T&() const {return t;} const T& t; }; template <typename T> struct isOneConversion : std::false_type {}; template <typename T> struct isOneConversion<OneConversion<T>> : std::true_type {}; struct Value { template<typename T, std::enable_if_t<!isOneConversion<T>::value>* = nullptr> Value(T) {} }; std::ostream &operator<<(std::ostream &os, const Value &value) { auto visitor = [&](auto a) -> decltype(os << OneConversion<decltype(a)>(a)) { return os << OneConversion<decltype(a)>(a); }; // Works visitor(Bar{}); visitor(Foo{}); // Error as expected. return os; }
auto visitor = [&](auto a) -> decltype( static_cast<std::ostream&(*)(std::ostream&, const decltype(a)&)>(&operator<<) (os, a) ) { return os << a; };
error: invalid static_cast from type '<unresolved overloaded function type>' to type 'std::ostream& (*)(std::ostream&, const Foo&