为什么Boost MPL具有积分常数?

Bre*_*ent 10 c++ boost metaprogramming boost-mpl c++11

既然你可以将整数值作为模板参数并对它们进行算术运算,那么boost :: mpl :: int _ <>和其他积分常数背后的动机是什么?这种动机是否仍然适用于C++ 11?

Jon*_*ely 13

tldr; 将值编码为类型允许它在比简单值更多的地方使用它.您可以在类型上重载,不能重载值.

K-Ballo的答案很棒.

我认为还有其他一些相关的东西.积分常量类型不仅可用作模板参数,它们可用作函数参数和函数返回类型(在我的示例中使用C++ 11类型,但相同的参数适用于早于它们的Boost):

template<typename R, typename... Args>
  std::integral_constant<std::size_t, sizeof...(Args)> 
  arity(R (*)(Args...))
  { return {}; }
Run Code Online (Sandbox Code Playgroud)

此函数接受一个函数指针并返回一个类型,告诉您该函数所使用的参数数量.在我们有constexpr函数之前,没有办法在常量表达式中调用函数,所以要问诸如"这个函数类型需要多少个参数?"之类的问题.你需要返回一个类型,并从中提取整数值.

即使constexpr在语言中(这意味着上面的函数可能只是return sizeof...(Args);整数值在编译时可用),仍然可以很好地使用整数常量类型,例如标签调度:

template<typename T>
  void frobnicate(T&& t)
  {
    frob_impl(std::forward<T>(t), std::is_copy_constructible<T>{});
  }
Run Code Online (Sandbox Code Playgroud)

frob_impl可以根据integer_constant<bool, b>作为第二个参数传递的类型重载此函数:

template<typename T>
  void frob_impl(T&& t, std::true_type)
  {
    // do something
  }

template<typename T>
  void frob_impl(T&& t, std::false_type)
  {
    // do something else
  }
Run Code Online (Sandbox Code Playgroud)

你可以尝试通过使boolean成为模板参数来做类似的事情:

frob_impl<std::is_copy_constructible<T>::value>(std::forward<T>(t));
Run Code Online (Sandbox Code Playgroud)

但是不可能部分专门化一个功能模板,所以你不能做frob_impl<true, T>frob_impl<false, T>做不同的事情.对布尔常量类型的重载允许您根据"is copy constructible"特性的轻松地执行不同的操作,在C++ 11中仍然非常有用.

常量有用的另一个地方是使用SFINAE实现特征.在C++ 03中,传统的方法是重载函数返回两种不同大小的类型(例如int,一个包含两个ints 的结构)并用它来测试"值" sizeof.在C++ 11中,函数可以返回true_type并且false_type更具表现力,例如测试"这种类型是否有一个成员调用foo?"的特征.可以使函数指示正结果返回true_type并使函数指示否定结果返回false_type,还有什么比这更清楚?

作为一个标准库实施者我做非常频繁使用的true_typefalse_type,因为很多编译时的"问题"有真/假答案,但是当我想测试的东西,可以有两个以上的不同的结果,我会用其他特integral_constant.


K-b*_*llo 12

您可以将整数值作为模板参数,但不能使用单个模板同时采用类型非类型模板参数.简而言之,将非类型模板参数视为类型允许它们与MPL中的无数事物一起使用.

例如,考虑一个find与类型一起工作的元函数,并在序列中查找相同的类型.如果您希望将其与非类型模板参数一起使用,则需要重新实现新算法的"重载",find_c您必须手动指定整数值的类型.现在想象一下,你希望它能够像其他语言一样使用混合积分类型,或者你想要混合类型非类型,你会得到一些"重载"的爆炸,这些过载也很难被使用,因为你有到处指定每个非类型参数的类型.

这种动机仍然适用于C++ 11.

这种动机仍适用于C++Ÿ和任何其他版本,除非我们有一些新的规则,允许从转换的非类型模板参数键入模板参数.例如,无论何时使用5和模板请求,类型都会实例化它std::integral_constant< int, 5 >.

  • C++ÿ?我以为是C++ 1y? (2认同)