有没有办法可以创建一个带有int
模板参数的函数,如果传递给函数的值小于10,那么该函数会产生编译时错误?
以下代码不起作用,但它显示了我想要完成的任务:
template <int number1>
void reportErrorIfLessThan10()
{
#if(number1 < 10)
#error the number is less than 10
#endif
}
int maint(int argc, char**argv)
{
reportErrorIfLessThan10<5>();//report an error!
reportErrorIfLessThan10<12>();//ok
return 0;
}
答案 0 :(得分:7)
如果你不想要Boost C++ Libraries魔法并想要骨头......
template<bool> class static_check
{
};
template<> class static_check<false>
{
private: static_check();
};
#define StaticAssert(test) static_check<(test) != 0>()
然后使用StaticAssert。这对我来说是一个#define,因为我的代码需要在很多C ++不适合模板的环境中运行,我需要将它备份到运行时断言。 :(
此外,不是最好的错误消息。
答案 1 :(得分:3)
template <int number1>
typename boost::enable_if_c< (number1 >= 10) >::type
reportErrorIfLessThan10() {
// ...
}
以上enable_if
,没有_c,因为我们有一个普通的bool,看起来像这样:
template<bool C, typename T = void>
struct enable_if {
typedef T type;
};
template<typename T>
struct enable_if<false, T> { };
Boost的enable_if
不是一个简单的bool,所以他们有另一个附加了_c的版本,它采用普通的bool。您将无法为number1
&lt; 10. SFINAE 会将该模板排除为可能的候选者,因为如果条件评估为enable_if
,::type
将不会公开类型false
。如果您因某种原因需要在功能中测试它,那么如果您有C++1x功能,则可以使用static_assert
:
template <int number1>
void reportErrorIfLessThan10() {
static_assert(number >= 10, "number must be >= 10");
}
如果没有,您可以使用BOOST_STATIC_ASSERT:
template <int number1>
void reportErrorIfLessThan10() {
BOOST_STATIC_ASSERT(number >= 10);
}
显示描述性消息的唯一方法是使用static_assert。您可以使用具有描述错误条件的名称的类型来或多或少地模拟它:
namespace detail {
/* chooses type A if cond == true, chooses type B if cond == false */
template <bool cond, typename A, typename B>
struct Condition {
typedef A type;
};
template <typename A, typename B>
struct Condition<false, A, B> {
typedef B type;
};
struct number1_greater_than_10;
}
template <int number1>
void reportErrorIfLessThan10() {
// number1 must be greater than 10
sizeof( typename detail::Condition< (number1 >= 10),
char,
detail::number1_greater_than_10
>::type );
}
它在这里打印:
错误:'sizeof'无效应用于不完整类型'detail :: number1_greater_than_10'
但我认为使用enable_if
的第一种方法就是这样做的。您将收到有关未申报reportErrorIfLessThan10
的错误消息。
答案 2 :(得分:3)
如果出于某种原因你不能使用Boost,这个例子很简单:
template <int number1>
void reportErrorIfLessThan10()
{
typedef char number1_gt_10[number1 > 10 ? 1 : -1];
}
int maint(int argc, char**argv)
{
reportErrorIfLessThan10<5>();//report an error!
reportErrorIfLessThan10<12>();//ok
return 0;
}
或更通用的
#define static_assert(test, message) typedef char static_assert_at_ ## __LINE__[(test) ? 1 : -1];
我没有连接错误消息本身,因为我觉得static_assert(true, "some message");
比static_assert(true, some_message);
更具可读性。但是,这确实将用例限制为每行只有一个断言。
答案 3 :(得分:0)
litb和Joe已经给出了实践中使用的答案。只是为了说明如何通过专门针对有问题的数字(而不是一般的布尔条件)手动完成:
template <int N>
struct helper : helper<N - 1> { };
template <>
struct helper<10> { typedef void type; };
template <>
struct helper<0> { }; // Notice: missing typedef.
template <int N>
typename helper<N>::type error_if_less_than_10() {
}
int main() {
error_if_less_than_10<10>();
error_if_less_than_10<9>();
}
函数不能继承,但类(和结构)可以。因此,此代码还使用一个结构,自动和动态生成除10和0之外的所有N的情况,这是硬编码的递归开始。
顺便说一句,上面的代码实际上提供了很好的错误消息:
x.cpp:16: error: no matching function for call to 'error_if_less_than_10()'