[英]Method outside template class with enable_if
我有以下代码,我想要一个模板 class 在初始化时将模板值检查为int64_t
或unint64_t
之一。 class 具有在 class 外部实现的GetValue
方法。
template <typename T, typename std::enable_if<std::is_same_v<T, int64_t> || std::is_same_v<T, uint64_t>>::type>
class Class
{
public:
Class(T value) noexcept :
cachedValue(value) {}
T GetValue() noexcept;
private:
T cachedValue;
};
template <typename T>
T Class<T>::GetValue() noexcept
{
// placeholder for now.
return cachedValue;
}
但是,即使在尝试了其他 SO 帖子的几个想法之后,我也遇到了来自enable_if
的构建错误C2955
、 C2956
、 C2976
或类似的东西。 我如何让这个工作?
问题
template <typename T,
typename std::enable_if<std::is_same_v<T, int64_t>
|| std::is_same_v<T, uint64_t>>::type>
class Class;
那是结果
template <typename T_OK, void> class Class;
或者
template <typename T_KO, /*Subsitution failure*/> class Class;
这两个都不正确。
对于不友好的情况(大多数情况下可能就足够了),您可以简单地使用static_assert
:
template <typename T> class Class
{
static_assert(std::is_same_v<T, int64_t> || std::is_same_v<T, uint64_t>);
/// ...
};
否则有几种变化(我会将条件缩短为cond_v<T>
)
常见的:(:
template <typename T, typename = std::enable_if_t<cond_v<T>>> class Class { ///... }; Class<int64_t> ok; Class<float> ko; // doesn't compile, as expected // but might be hijacked: Class<float, void> hijacked; // compile, unexpected
固定的:
template <typename T, std::enable_if_t<cond_v<T>, int> = 0> class Class { ///... }; Class<int64_t> ok; Class<float> ko; // doesn't compile, as expected
一种允许定制的
template <typename T, typename = void> class Class; template <typename T> class Class<T, std::enable_if_t<cond_v<T>>> { ///... }; Class<int64_t> ok; Class<float> ko; // incomplete type: doesn't compile, as expected // user might add additional specialization: template <typename T> class Class<std::vector<T>, void> {/*..*/};
最适用于创建可定制的特征(因为您专门研究整个班级)。
C++20 引入了更短和简化语法的概念:
restreint 允许的类型(有几种等效的语法)
template <typename T> requires(cond_v<T>) class Class { /*..*/};
允许定制,采取最好的专业化:
template <typename T> class Class; // Specialization template <typename T> requires(cond_v<T>) class Class<T> { /*..*/};
您可以使用 @WhozCraing 方法,使用static_assert
提供一些消息/指令或使用C++20
的Concepts
,如下所示
template<class T>
concept ints64 = std::is_same_v<T, int64_t> || std::is_same_v<T, uint64_t>;
template <typename T> requires(ints64<T>)
struct Class{
Class(T value) noexcept : cachedValue(value) {}
T GetValue() noexcept;
private:
T cachedValue;
};
template <typename T>requires(ints64<T>)
T Class<T>::GetValue() noexcept{
return cachedValue;
}
int main(){
return Class<int64_t>{0}.GetValue();//return Class<int>{0}.GetValue(); won't compile
}
在 C++20 之前,还有一种使 class 模板对 SFINAE 友好的传统方法:
template<typename T, typename = void>
class Class; // <1> you can define it here if the conditions are not satisfied.
template<typename T>
class Class<T, typename std::enable_if<std::is_same_v<T, int64_t> || std::is_same_v<T, uint64_t>>::type>{
public:
Class(T value) noexcept :cachedValue(value) {}
T GetValue() noexcept;
private:
T cachedValue;
};
int main(){
Class<int64_t> a = 0; // ok
Class<uint64_t> b = 0; // ok
Class<int32_t> c = 0; // incomplete-type. you can define it at <1>.
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.