简体   繁体   English

如何将模板类限制为某些内置类型?

[英]How do I restrict a template class to certain built-in types?

This issue has been discussed a few times but all the solutions I have found either didn't work or were based on boost's static assert.这个问题已经讨论过几次,但我发现的所有解决方案要么不起作用,要么基于 boost 的静态断言。 My problem is simple.我的问题很简单。 I have a class, and I only want to allow real types (double and float).我有一个类,我只想允许真正的类型(double 和 float)。 I want a compile-time error if I try to instantiate the class with a type other than float or double.如果我尝试使用 float 或 double 以外的类型实例化类,我想要一个编译时错误。 I am using Visual C++ 11. Here is what I have tried:我正在使用 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);
}

Any ideas?有任何想法吗? Thanks in advance!提前致谢!

In your first example, static_assert should take a second parameter which would be a string literal, otherwise it's deemed to fail ( edit: dropping the the second parameter is legal since C++17).在你的第一个例子中, static_assert应该采用第二个参数,这将是一个字符串文字,否则它被视为失败(编辑:从 C++17 开始删除第二个参数是合法的)。 And this second argument cannot be defaulted.这第二个参数不能被默认。

Your second example is incorrect for several reasons:由于以下几个原因,您的第二个示例不正确:

  • decltype is meant to be used on an expression, not on a type. decltype旨在用于表达式,而不是用于类型。
  • You simply cannot compare types with == , the correct way to do this is what you try in your first attempt with std::is_same .您根本无法将类型与==进行比较,正确的方法是您在第一次尝试使用std::is_same尝试的std::is_same

So, the right way to do what you are trying to achieve is:因此,做您想要实现的目标的正确方法是:

#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");
};

Moreover, I bet you are trying to constrict your template to floating points values.此外,我敢打赌您正试图将您的模板限制为浮点值。 In order to do this, you can use the trait std::is_floating_point :为此,您可以使用特征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");
};

And as a bonus, take this online example .作为奖励,以这个在线示例为例

One solution I've seen is to use std::enable_if in a type alias.我见过的一种解决方案是在类型别名中使用std::enable_if Something like:就像是:

using value_type = typename std::enable_if<
                    std::is_same<float, RealType>::value ||
                    std::is_same<double, RealType>::value,
                    RealType
                >::type;

value_type only exists if RealType is exactly float or double . value_type仅在RealType恰好是floatdouble时才存在。 Otherwise, the type is undefined and compilation fails.否则,类型未定义且编译失败。

I'd warn about being too strict with types, though.不过,我会警告对类型过于严格。 Templates are as powerful as they are partly because the duck typing they do means that any type that can be used the way you want to use it, will work.模板之所以强大,部分原因在于它们所做的鸭式输入意味着任何可以按照您想要的方式使用的类型都可以使用。 Disallowing types for the sake of disallowing types generally doesn't gain you much, and can make things less flexible than they could be.为了禁止类型而禁止类型通常不会给您带来太多好处,并且会使事情变得不那么灵活。 For example, you wouldn't be able to use a type with more precision, like a big-decimal type.例如,您将无法使用更精确的类型,如大十进制类型。

This way it also allows specialization for various types:通过这种方式,它还允许对各种类型进行专业化:

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 concept usage C++20 概念用法

https://en.cppreference.com/w/cpp/language/constraints cppreference is giving as similar example for inheritance as I mentioned at: C++ templates that accept only certain types and by guessing from that I think the syntax for specific classes will be: 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);

but I haven't been able to test this yet due to compiler support as explained in that other answer.但由于编译器支持,如其他答案中所述,我还无法对此进行测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM