模板参数中的enable_if创建模板重新定义错误
enable_if in template Parameters Creates Template Redefinition Error
在这个答案中,我真正想做的是在我的模板参数中定义一个typename
,它可以用于强制转换和返回。
所以这个:
template <typename T>
auto caster(T value)
-> typename std::enable_if<sizeof(unsigned char) == sizeof(T), unsigned char>::type
{ return reinterpret_cast<unsigned char&>(value); }
会变成这样:
template <typename T, typename R = std::enable_if<sizeof(unsigned char) == sizeof(T), unsigned char>::type >
R caster(T value) { return reinterpret_cast<R&>(value); }
这对于单个模板专业化来说是可以正常工作和行为的,但我需要添加另一个重载:
template <typename T, typename R = std::enable_if<sizeof(short) == sizeof(T), short>::type>
R caster(T value) { return reinterpret_cast<R&>(value); }
现在我得到一个错误:
错误C2995:"R caster(T)":已定义功能模板
有没有一种方法可以让编译器相信,对于任何给定的调用,这些专业化中只有一个会真正构建?
不,没有。模板默认参数就是这样,默认。任何用户都可以调用caster<short, short>
,这将匹配两个重载。
但是,可以添加更多的伪参数。
template <typename T,
typename R = typename std::enable_if<sizeof(unsigned char) == sizeof(T), unsigned char>::type >
R caster(T value) { return reinterpret_cast<R&>(value); }
template <typename T,
typename R = typename std::enable_if<sizeof(short) == sizeof(T), short>::type,
typename = void>
R caster(T value) { return reinterpret_cast<R&>(value); }
(还要注意添加的typename
。)
然而,由于所有的身体都是一样的,我可能不会选择过载。
template <std::size_t N>
struct cast_result;
template <>
struct cast_result<sizeof(std::uint8_t)> {
typedef std::uint8_t type;
};
template <>
struct cast_result<sizeof(std::uint16_t)> {
typedef std::uint16_t type;
};
...
template <typename T, typename R = typename cast_result<sizeof(T)>::type>
R caster(T value) {
return reinterpret_cast<R&>(value);
}
最后要注意的是:reinterpret_cast
的使用违反了混叠规则。然而,这很容易解决:
template <typename T, typename R = typename cast_result<sizeof(T)>::type>
R caster(T value) {
R result;
std::memcpy(&result, &value, sizeof result);
return result;
}
这里最好的解决方案可能是使用大量的conditional
,这将防止我不得不篡改模板专业化:
template <typename T, typename R = std::conditional<sizeof(T) == sizeof(unsigned char),
unsigned char,
conditional<sizeof(T) == sizeof(unsigned short),
unsigned short,
conditional<sizeof(T) == sizeof(unsigned long),
unsigned long,
enable_if<sizeof(T) == sizeof(unsigned long long), unsigned long long>::type>::type>::type>::type>
R caster(T value){ return reinterpret_cast<R&>(value); }
我向读者道歉,因为这就像阅读嵌套的燕鸥。然而,我目前还不知道有什么更干净的方法来处理这个问题。
遗憾的是,这仍然不能阻止用户通过提供hvd提到的他自己的第二个模板参数来践踏我的所有默认值。
编辑:
我在这里问了另一个问题,它的解决方案不需要将typename
放在模板定义中,也不需要声明两次类型。
相关文章:
- 定义C++新的环境变量并在 bat 文件中使用它
- 是否可以使用单个定义定义函数的常量和常规版本?(使用模板,自动,decltype等)
- 从使用概念定义的函数返回新对象
- 如何在C++中为 if 和 else 语句定义新行为
- 如何从 C++ 中的现有模板函数定义新函数
- 自定义分配器,包括放置新案例
- 正在通过const-ref未定义的行为捕获新构造的对象
- 如何在CPropertySheet中定义新颜色
- 谁定义新操作员
- 未定义的符号'fixed_address_empty_string':带有protobuf的新张量流运算
- 新的C ,未定义的参考
- boost :: fibonacci_heap:带有比较器重新定义圆形定义错误的嵌套定义
- 宏,用于定义带有添加前缀的新宏
- 取消脱壳:使用模板在多行类型定义中添加一个尖括号后的新行
- C 通过Typedef定义新类型
- 通过在此指针上放置新位置重新初始化对象时未定义的行为
- 在 ss.clear() 之后使用 ss.str( " ") 用于新定义的字符串流
- Eclipse CDT将方法定义定义到标头文件
- 是标头文件中使用“新”定义的成员指针泄漏
- LEX 程序中的未定义定义