32

这个问题已经讨论过几次,但我发现的所有解决方案要么不起作用,要么基于 boost 的静态断言。我的问题很简单。我有一堂课,我只想允许真正的类型(双精度和浮点数)。如果我尝试使用浮点或双精度以外的类型实例化类,我想要一个编译时错误。我正在使用 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);
}

有任何想法吗?提前致谢!

4

4 回答 4

40

在您的第一个示例中,static_assert应该采用第二个参数,该参数将是字符串文字,否则将被视为失败(编辑:删除第二个参数自 C++17 以来是合法的)。而这第二个参数不能被默认。

您的第二个示例不正确有几个原因:

  • decltype旨在用于表达式,而不是类型。
  • 您根本无法将类型与 进行比较==,正确的方法是您在第一次尝试时尝试使用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");
};

此外,我敢打赌您正试图将您的模板限制为浮点值。为此,您可以使用 trait 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");
};

作为奖励,以这个在线示例为例

于 2013-06-07T06:57:05.183 回答
29

我见过的一种解决方案是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仅当RealTypefloat或时才存在double。否则,类型未定义,编译失败。

不过,我会警告不要对类型过于严格。模板之所以如此强大,部分原因是它们所做的鸭式打字意味着任何可以按照您想要使用的方式使用的类型都可以使用。为了禁止类型而禁止类型通常不会给您带来太多好处,并且会使事情变得不那么灵活。例如,您将无法使用精度更高的类型,例如大十进制类型。

于 2013-06-07T06:00:28.240 回答
6

通过这种方式,它还允许对各种类型进行专门化:

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> {

};
于 2013-06-07T07:14:50.797 回答
2

C++20 概念用法

https://en.cppreference.com/w/cpp/language/constraints cppreference 给出了与我在以下位置提到的类似的继承示例:C++ templates that accept only certain types and by guessing from that I think the syntax for specific classes will是:

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);

但由于编译器支持,我还无法对此进行测试,正如其他答案中所解释的那样。

于 2020-05-08T10:05:35.637 回答