限制 Class 模板类型
Limiting Class Template Types
我正在尝试使用 SFINAE 来限制我正在编写的 class 允许的模板参数类型。这是我想出的一个简单的人为示例,我相信它说明了我想做的事情。
我确定这个问题已经在某个地方得到了回答,但我找不到。
以下是我找到的两种解决问题的方法:
第一名(SFINAE):
template <typename T, typename = typename std::enable_if<std::is_same<T, int>::value>::type>
class Integer {
public:
T value;
};
int main() {
Integer<int> i; // Alowed
Integer<double> d; // Not allowed
Integer<double, double> dd; // Allowed (Undesired)
return 0;
}
我不喜欢这个解决方案的原因是主函数中的第三个示例有效。
第二(static_assert):
#include <type_traits>
template <typename T>
class Integer {
static_assert(std::is_same<T, int>::value, "T must be int");
public:
T value;
};
int main() {
Integer<int> i; // Allowed
Integer<double> d; // Not allowed
return 0;
}
我认为这个解决方案很好,但我想知道是否有更优雅或 SFINAE 的方式来完成同样的事情。
在这种情况下,对于这个简单的示例,我希望能够强制模板类型 T 必须是整数。当然,在这种情况下 class 甚至不需要是模板,我可以将 Integer class 中的类型声明为 int 类型,但我想使用我在这里学到的东西在更复杂的情况下。
您可以使用未命名的非类型模板参数修复您的第一个示例。将其更改为
template <typename T, std::enable_if_t<std::is_same_v<T, int>, bool> = true>
class Integer {
public:
T value;
};
将只允许 Integer<int> i;
编译。它还会阻止用户尝试使用 Integer<double, true> dd;
绕过它
以另一种(正确的)方式使用 SFINAE:
template <typename T, typename std::enable_if<std::is_same<T, int>::value, int>::type = 0>
class Integer {
public:
T value;
};
不再劫持。
我正在尝试使用 SFINAE 来限制我正在编写的 class 允许的模板参数类型。这是我想出的一个简单的人为示例,我相信它说明了我想做的事情。
我确定这个问题已经在某个地方得到了回答,但我找不到。
以下是我找到的两种解决问题的方法:
第一名(SFINAE):
template <typename T, typename = typename std::enable_if<std::is_same<T, int>::value>::type>
class Integer {
public:
T value;
};
int main() {
Integer<int> i; // Alowed
Integer<double> d; // Not allowed
Integer<double, double> dd; // Allowed (Undesired)
return 0;
}
我不喜欢这个解决方案的原因是主函数中的第三个示例有效。
第二(static_assert):
#include <type_traits>
template <typename T>
class Integer {
static_assert(std::is_same<T, int>::value, "T must be int");
public:
T value;
};
int main() {
Integer<int> i; // Allowed
Integer<double> d; // Not allowed
return 0;
}
我认为这个解决方案很好,但我想知道是否有更优雅或 SFINAE 的方式来完成同样的事情。
在这种情况下,对于这个简单的示例,我希望能够强制模板类型 T 必须是整数。当然,在这种情况下 class 甚至不需要是模板,我可以将 Integer class 中的类型声明为 int 类型,但我想使用我在这里学到的东西在更复杂的情况下。
您可以使用未命名的非类型模板参数修复您的第一个示例。将其更改为
template <typename T, std::enable_if_t<std::is_same_v<T, int>, bool> = true>
class Integer {
public:
T value;
};
将只允许 Integer<int> i;
编译。它还会阻止用户尝试使用 Integer<double, true> dd;
以另一种(正确的)方式使用 SFINAE:
template <typename T, typename std::enable_if<std::is_same<T, int>::value, int>::type = 0>
class Integer {
public:
T value;
};
不再劫持。