带有算术表达式的boost :: enable_if

时间:2017-03-15 10:57:19

标签: boost enable-if

我有一个自定义字符串类,其长度为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

1 个答案:

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

关于您的示例,有几点需要注意:

  • 与C ++ 11中的std::enable_if不同,boost::enable_ifboost::disable_if接受元函数作为其第一个模板参数。元函数是一个具有嵌套静态成员变量value的类,它是元函数的结果。 Boost还提供boost::enable_if_cboost::disable_if_c模板,与std::enable_if一样,直接接受布尔常量。因此,如果要检查长度是否大于8,您只需写下:
typename boost::enable_if_c< (LEN > 8) >::type

请注意,在括号中采用条件以避免解析错误,因为否则较大的运算符将被解释为结束尖括号。

  • 一些破碎的编译器遇到如上所述的常量表达式问题。对于那些编译器,可能有必要将条件表示为元函数。 Boost.MPL可以为您提供帮助:
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中,编译器错误将包含内联消息。