作者热门文章
- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有
Value 类,可以用不同类型(Foo、Bar、int、...)构造。
class Value 应该有常见的操作,如 <<、==、<、... 在基础类型上进行
我在类定义之外添加了运算符 <<。
我需要以下代码:
#include <iostream>
struct Foo {
};
struct Bar {
};
struct Value {
template<typename T>
Value(T) {
}
};
std::ostream &operator<<(std::ostream &os, const Bar &) {
return os << "Bar\n";
}
std::ostream &operator<<(std::ostream &os, const Value &value) {
auto visitor = [&](auto a) -> decltype(os << a) {
return os << a;
};
// Works
visitor(Bar{});
// Infinity call of this function with Value.
visitor(Foo{});
return os;
}
int main() {
std::cout << Value(1);
return 0;
}
问题:如果底层类型没有实现运算符<<,Value 中的运算符<< 会被称为递归无限。我想得到一个编译器错误,例如 no match for call operator<<(std:ostream&, const Value&)... 以将 SFINAE 与我的访问者模式一起使用(此处未显示)。
我需要的是这样的:
[&](auto a) -> std::enable_if_t<addressof?(os << a) != addressof?(os << Value{})>::value> {
return os << a;
};
如果功能相同,则禁用此 lambda。这可能吗?
没有值(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;
}
关于c++ - SFINAE 用于泛型类型的泛型操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46772840/
我是一名优秀的程序员,十分优秀!