使用type_traits来限制模板成员函数的类型

时间:2016-04-06 20:03:54

标签: c++ typetraits

我正在编写一个带有执行某些按位操作的方法的模板类,因此我希望在is_integral中使用此方法的情况下限制类型。我拿了一个简单的例子here并修改了一下如下:

#include <iostream>
#include <type_traits>

template <typename T>
class A
{
  public:
    A();

    T foo(T i) {
        static_assert(std::is_integral<T>::value, "Integer required.");
        return (i & 2);
    }

  private:
    T x;
};

int main() {
  A<double> a;
  std::cout << a.foo(3) << std::endl;

  return 0;
}

但是,编译器在static_assert()处给出了2个编译错误:

static_assert failed "Integer required."

return (i & 2);

invalid operands to binary expression ('double' and 'double')

我的问题是,如果它会在return (i & 2);行显示错误,使用type_traits来检查这里的类型似乎没用?并且,无论如何在运行时将错误抛出到控制台输出,而不是让它无法编译?

3 个答案:

答案 0 :(得分:1)

  

我的问题是,如果它会在return (i & 2);行显示错误,使用type_traits来检查这里的类型似乎没用?

不幸的是,无论如何你都会得到后续的编译错误,但是你觉得哪个编译错误更具可读性呢?

  • &#34;需要整数。&#34;
  • 二进制表达式的无效操作数(doubledouble

我知道我对第一个做错了什么 - 我有A<double>foo()需要一个整数。不知道第二个。我是否滥用您的班级模板或是否有错误?

  

而且,无论如何在运行时将错误抛给控制台输出,而不是让它无法编译?

希望它是一个编译错误。在编译时捕获错误比在编译时捕获错误要好得多。

答案 1 :(得分:0)

编译器正试图报告尽可能多的错误。 static_assert报告错误,但也有另一个错误(使用double的{​​{1}}参数),因此也会报告错误。

如果要将输出限制为一个错误,则应该有两个启用sfinae的重载,并且第二个(除了积分之外的任何内容)由一个&组成。

至于你的上一个问题,做static_assert的整个目的是在编译时触发错误,而不是运行时。

答案 2 :(得分:0)

这是实现同样目标的另一种方式。您可能喜欢也可能不喜欢错误消息:

#include <iostream>
#include <type_traits>

template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
class A
{
  public:
    A();

    T foo(T i) {
        return (i & 2);
    }

  private:
    T x;
};

int main() {
  A<double> a;
  std::cout << a.foo(3) << std::endl;

  return 0;
}

示例错误:

In file included from /opt/gcc-5.3.0/include/c++/5.3.0/bits/move.h:57:0,
from /opt/gcc-5.3.0/include/c++/5.3.0/bits/stl_pair.h:59,
from /opt/gcc-5.3.0/include/c++/5.3.0/bits/stl_algobase.h:64,
from /opt/gcc-5.3.0/include/c++/5.3.0/bits/char_traits.h:39,
from /opt/gcc-5.3.0/include/c++/5.3.0/ios:40,
from /opt/gcc-5.3.0/include/c++/5.3.0/ostream:38,
from /opt/gcc-5.3.0/include/c++/5.3.0/iostream:39,
from /tmp/gcc-explorer-compiler11636-75-1ve7gbt/example.cpp:1:
/opt/gcc-5.3.0/include/c++/5.3.0/type_traits: In substitution of 'template<bool _Cond, class _Tp> using enable_if_t = typename std::enable_if::type [with bool _Cond = std::integral_constant<bool, false>::value; _Tp = void]':
19 : required from here
/opt/gcc-5.3.0/include/c++/5.3.0/type_traits:2388:61: error: no type named 'type' in 'struct std::enable_if<false, void>'
using enable_if_t = typename enable_if<_Cond, _Tp>::type;
^
/tmp/gcc-explorer-compiler11636-75-1ve7gbt/example.cpp: In function 'int main()':
19 : error: template argument 2 is invalid
A<double> a;
^
20 : error: request for member 'foo' in 'a', which is of non-class type 'int'
std::cout << a.foo(3) << std::endl;
^
Compilation failed