enable_if 在模板参数中创建模板重新定义错误
enable_if in template Parameters Creates Template Redefinition Error
在 中,我真正想做的是在我的模板参数中定义一个 typename
,它可以用于转换 和 return.
所以这个:
template <typename T>
typename std::enable_if<sizeof(unsigned char) == sizeof(T), unsigned char>::type caster(T value){ 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); }
现在我得到一个错误:
error C2995: 'R caster(T)' : function template has already been defined
有没有办法让编译器相信这些特化中只有一个会为任何给定调用实际构建?
不,没有。模板默认参数就是 defaults。任何用户都可以调用 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
s,这将防止我不得不愚弄模板特化:
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); }
我对 reader 表示歉意,因为它就像阅读嵌套的三元组。但是我目前不知道有更简洁的方法来处理这个问题。
遗憾的是,这仍然无法阻止用户通过提供他自己的第二个模板参数来践踏我的所有默认设置,如 hvd 所述。
编辑:
我问了另一个问题 有一个解决方案不需要在模板定义中放置 typename
而 不需要需要声明类型两次。
在 typename
,它可以用于转换 和 return.
所以这个:
template <typename T>
typename std::enable_if<sizeof(unsigned char) == sizeof(T), unsigned char>::type caster(T value){ 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); }
现在我得到一个错误:
error C2995: 'R caster(T)' : function template has already been defined
有没有办法让编译器相信这些特化中只有一个会为任何给定调用实际构建?
不,没有。模板默认参数就是 defaults。任何用户都可以调用 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
s,这将防止我不得不愚弄模板特化:
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); }
我对 reader 表示歉意,因为它就像阅读嵌套的三元组。但是我目前不知道有更简洁的方法来处理这个问题。
遗憾的是,这仍然无法阻止用户通过提供他自己的第二个模板参数来践踏我的所有默认设置,如 hvd 所述。
编辑:
我问了另一个问题 typename
而 不需要需要声明类型两次。