C++ 模板类默认类型和条件
我想对MyClass使用std::enable_if以便只接受(uint32_t | uint64_t),同时如果用户没有提供任何类型;根据以下条件选择默认值 但我不能让它工作。(C++17)C++ 模板类默认类型和条件,c++,templates,default,enable-if,conditional-types,C++,Templates,Default,Enable If,Conditional Types,我想对MyClass使用std::enable_if以便只接受(uint32_t | uint64_t),同时如果用户没有提供任何类型;根据以下条件选择默认值 但我不能让它工作。(C++17) #包括 #包括 模板 类MyClass { 私人: std::向量vs; 公众: // ... }; int main(){ MyClass a;//好的,defaut类型使用uint32\u t或uint64\u t MyClass b;//好的,使用用户提供的类型 MyClass c;//不能编译,T
#包括
#包括
模板
类MyClass
{
私人:
std::向量vs;
公众:
// ...
};
int main(){
MyClass a;//好的,defaut类型使用uint32\u t或uint64\u t
MyClass b;//好的,使用用户提供的类型
MyClass c;//不能编译,T不是uint32\u T、uint64\u T中的一个
}
您可以添加以执行检查
template <typename T=std::conditional_t<sizeof(void*) == 8, std::uint64_t, std::uint32_t>>
class MyClass
{
static_assert(std::is_same_v<T, std::uint64_t> || std::is_same_v<T, std::uint32_t>, "T must be std::uint64_t or std::uint32_t");
private:
std::vector<T> vs;
public:
// ...
};
模板
类MyClass
{
静态断言(std::is_same_v | std::is_same_v,“T必须是std::uint64或std::uint32_T”);
私人:
std::向量vs;
公众:
// ...
};
宋彦尧用
静态断言提出的解决方案是好的、完全有效的,并且比我下面建议的要短。然而
建议另一种选择,让编译器在不需要静态断言的情况下检查您:
template <typename T>
class MyClassBase {
std::vector<T> vs;
public:
// ...
};
template <typename T =
std::conditional_t<sizeof(void*) == 8, std::uint64_t, std::uint32_t>>
class MyClass;
template <>
class MyClass<std::uint64_t>: public MyClassBase<std::uint64_t> {};
template <>
class MyClass<std::uint32_t>: public MyClassBase<std::uint32_t> {};
模板
类MyClassBase{
std::向量vs;
公众:
// ...
};
模板
类MyClass;
模板
类MyClass:公共MyClassBase{};
模板
类MyClass:公共MyClassBase{};
若指针的大小较小,您会怎么做?承认,它们很罕见,但仍然有一些16位µC存在。。。(当然,uint32\u t也适用于这些测试)。我个人更喜欢测试sizeof(void*)==sizeof(uint64\u t)
。承认,同样罕见,但即使在今天,一些专门的机器仍有CHAR\u BIT==16
…限制字体宽度的真正原因是什么?也许像std::is_integral&&std::is_unsigned
这样的东西更可取std::uintptr\u t
可能是一个很好的默认值,用户甚至可以在系统/编译器上使用一个128位无符号整数,提供一个……如果出于任何原因都没有可用的static\u assert
,这很好。好的,std::conditional
可能也不是,但这很容易单独实现。缺点:一个必须维护两个实现。@Aconcaguastatic\u assert
意味着可以创建类型,但我们通过代码中的某个地方禁止它。假设其他编译单元的某个人添加了显式专门化模板类MyClass{}代码>。人们可能会认为,静态断言
禁止它,但事实并非如此。在我的方法中,类型根本不存在,除非您创建它。没有魔法。但是,这两种方法都是有效的。有效的区别是什么?两种方法都只允许将模板用于所需的两种类型,并且两种方法都允许通过添加另一种专门化来规避(所需!)限制。我很清楚背后的技术差异,但这不是我的观点——相反,当被迫为C++03或更高版本编译时,您也可以使用您的方法,而另一种方法则不能。即使在C++11使用了近十年之后的今天,这种限制仍然存在。。。
template <typename T>
class MyClassBase {
std::vector<T> vs;
public:
// ...
};
template <typename T =
std::conditional_t<sizeof(void*) == 8, std::uint64_t, std::uint32_t>>
class MyClass;
template <>
class MyClass<std::uint64_t>: public MyClassBase<std::uint64_t> {};
template <>
class MyClass<std::uint32_t>: public MyClassBase<std::uint32_t> {};