[英]How do I restrict a template class to certain built-in types?
这个问题已经讨论过几次,但我发现的所有解决方案要么不起作用,要么基于 boost 的静态断言。 我的问题很简单。 我有一个类,我只想允许真正的类型(double 和 float)。 如果我尝试使用 float 或 double 以外的类型实例化类,我想要一个编译时错误。 我正在使用 Visual C++ 11。这是我尝试过的:
template <typename RealType>
class A
{
// Warning C4346
static_assert(std::is_same<RealType, double>::value || std::is_same<RealType, float>::value);
}
template <typename RealType>
class A
{
// Error C2062: type 'unknown' unexpected
static_assert(decltype(RealType) == double || decltype(RealType) == float);
}
有任何想法吗? 提前致谢!
在你的第一个例子中, static_assert
应该采用第二个参数,这将是一个字符串文字,否则它被视为失败(编辑:从 C++17 开始删除第二个参数是合法的)。 这第二个参数不能被默认。
由于以下几个原因,您的第二个示例不正确:
decltype
旨在用于表达式,而不是用于类型。==
进行比较,正确的方法是您在第一次尝试使用std::is_same
尝试的std::is_same
。因此,做您想要实现的目标的正确方法是:
#include <type_traits>
template <typename RealType>
class A
{
static_assert(std::is_same<RealType, double>::value || std::is_same<RealType, float>::value,
"some meaningful error message");
};
此外,我敢打赌您正试图将您的模板限制为浮点值。 为此,您可以使用特征std::is_floating_point
:
#include <type_traits>
template <typename RealType>
class A
{
static_assert(std::is_floating_point<RealType>::value,
"class A can only be instantiated with floating point types");
};
作为奖励,以这个在线示例为例。
我见过的一种解决方案是在类型别名中使用std::enable_if
。 就像是:
using value_type = typename std::enable_if<
std::is_same<float, RealType>::value ||
std::is_same<double, RealType>::value,
RealType
>::type;
value_type
仅在RealType
恰好是float
或double
时才存在。 否则,类型未定义且编译失败。
不过,我会警告对类型过于严格。 模板之所以强大,部分原因在于它们所做的鸭式输入意味着任何可以按照您想要的方式使用的类型都可以使用。 为了禁止类型而禁止类型通常不会给您带来太多好处,并且会使事情变得不那么灵活。 例如,您将无法使用更精确的类型,如大十进制类型。
通过这种方式,它还允许对各种类型进行专业化:
template<typename T, typename Enable = void>
class A {
/// Maybe no code here or static_assert(false, "nice message");
};
/// This specialization is only enabled for double or float.
template<typename T>
class A<T, typename enable_if<is_same<T, double>::value || is_same<T, float>::value>::type> {
};
C++20 概念用法
https://en.cppreference.com/w/cpp/language/constraints cppreference 给出了类似的继承示例,正如我在: 仅接受某些类型的 C++ 模板,并从中猜测我认为特定类的语法将是:
template <class T, class Class1, class Class2>
concept Derived = std::is_same<U, Class1>::value || std::is_same<U, Class2>::value;
template<Derived<MyClass1, MyClass2> T>
void f(T);
但由于编译器支持,如其他答案中所述,我还无法对此进行测试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.