我正在编写一个带有执行某些按位操作的方法的模板类,因此我希望在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
来检查这里的类型似乎没用?并且,无论如何在运行时将错误抛出到控制台输出,而不是让它无法编译?
答案 0 :(得分:1)
我的问题是,如果它会在
return (i & 2);
行显示错误,使用type_traits
来检查这里的类型似乎没用?
不幸的是,无论如何你都会得到后续的编译错误,但是你觉得哪个编译错误更具可读性呢?
double
和double
)我知道我对第一个做错了什么 - 我有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