我有一个自定义字符串类,其长度为specialized参数。长度应至少为9个字符,我想将其作为编译时检查。
我希望为此使用boost :: enable_if,但我很难搞清楚语法。我希望有类似boost :: is_greater的东西,类似于boost :: same_as,如下所示。但是我找不到要放入enable_if模板参数的表达式。有人可以帮忙吗?
不幸的是我不能使用C ++ 11。
=Datediff("h",Fields!StartDate.value,Fields!EndDate.value) & ":" & Datediff("n",Fields!StartDate.value,Fields!EndDate.value) mod 60 & ":" & Datediff("s",Fields!StartDate.value,Fields!EndDate.value) mod 60
答案 0 :(得分:2)
boost::enable_if
允许人们使用SFINAE,这在某些情况下会有所帮助,而在其他情况下则不合适。通常,如果要根据某些条件禁用某些代码分支而不生成硬编译错误,则需要使用SFINAE,这通常意味着该案例将由另一个分支处理。例如,可以根据某些条件选择要调用的函数重载。
struct A {};
// This overload gets called for any type T that derives from A or for A itself
template< typename T >
typename boost::enable_if< typename boost::is_base_of< A, T >::type >::type
foo(T const& t);
// This overload is selected for any other types
template< typename T >
typename boost::disable_if< typename boost::is_base_of< A, T >::type >::type
foo(T const& t);
关于您的示例,有几点需要注意:
std::enable_if
不同,boost::enable_if
和boost::disable_if
接受元函数作为其第一个模板参数。元函数是一个具有嵌套静态成员变量value
的类,它是元函数的结果。 Boost还提供boost::enable_if_c
和boost::disable_if_c
模板,与std::enable_if
一样,直接接受布尔常量。因此,如果要检查长度是否大于8,您只需写下:typename boost::enable_if_c< (LEN > 8) >::type
请注意,在括号中采用条件以避免解析错误,因为否则较大的运算符将被解释为结束尖括号。
typename boost::enable_if<
boost::mpl::greater<
boost::mpl::int_< LEN >,
boost::mpl::int_< 8 >
>
>::type
这里,boost::mpl::greater
是产生比较结果的元函数;此结果由boost::enable_if
获取。
enable_if<>::type
嵌套类型非常重要。对于类,这基本上相当于专业化中的模板参数列表。// Generic template. Used whenever none of the specializations apply.
template< int LEN, class Enable = void >
class MyString
{
};
// Specialization. Used if LEN > 8 is true because
// its second template argument (Enable, which is void by default)
// matches the type produced by enable_if_c, which is also void
// if the condition is true.
template< int LEN >
class MyString< LEN, typename boost::enable_if_c< (LEN > 8) >::type >
{
};
因此,此代码根据条件有效地选择特化。如果您希望MyString
仅适用于满足条件的情况,则可以保留主模板未定义(即仅保留声明):
// Generic template. Used whenever none of the specializations apply.
template< int LEN, class Enable = void >
class MyString;
如果您确实想要在违反某些编译时前置条件时生成硬错误,那么使用静态断言可能更合适。在C ++ 11中,它是用static_assert
完成的,在C ++ 03中你可以使用Boost.StaticAssert:
template< int LEN >
class MyString
{
BOOST_STATIC_ASSERT_MSG(LEN > 8, "String length must be greater than 8");
};
在这种情况下,不需要专业化,作为额外奖励,您将获得更好的错误消息。在C ++ 03中,它会谈到静态断言失败,指向断言行,用简单的语言解释问题。在C ++ 11中,编译器错误将包含内联消息。