为什么std :: result_of将(不相关的)函数类型作为类型参数?

时间:2013-03-18 21:07:15

标签: c++ boost c++11 std

我意识到“为什么事情就像他们一样”问题通常不是最好的问题,但是有很多人都在调整标准委员会的讨论,所以我希望这可以在事实上得到回答,因为我合法地好奇至于答案是什么。

基本上,我第一次看到它时花了很长时间才弄清楚std::result_of的模板签名是怎么回事:我认为这是一个全新的模板参数构造,我从来没有之前见过。

template< class F, class... ArgTypes >
class result_of<F(ArgTypes...)>;

经过一段时间的思考后,我意识到这实际上是什么:F(ArgTypes...)是一个函数类型,但它是正在评估其结果类型的函数的类型(即只是F):这是一个采用ArgTypes...参数和返回类型F的函数类型。

这不是......奇怪吗?有点hackish?有没有人知道委员会是否讨论过任何替代方案,例如,以下......

template< class F, class... ArgTypes >
class result_of<F, ArgTypes...>;

我想有可能存在第二种结构不能像第一种结构那样容易使用的情况,但是哪种情况呢?

我不是试图对此作出判断,但只是在我第一次看到它时这对我来说是合法的混淆,所以我很好奇是否有充分的理由。我意识到部分答案可能只是“因为Boost这样做了”,但仍留下剩下的(事实)问题...

  • 是否存在技术原因Boost选择此语法来编码类型信息而不是任何替代方法?

  • C ++ 11委员会是否有任何关于标准化这一点的适当性的讨论,因为std::result_of可以相当容易地以decltype方式实现?

4 个答案:

答案 0 :(得分:17)

使用函数类型作为参数,即使在C ++ 03中也可以使用不受限制的“可变参数”类模板。想一想:在C ++ 03中,我们没有可变参数模板。并且你不能像使用函数模板那样“重载”类模板 - 那么如何在函数中允许不同数量的“参数”呢?

使用函数类型,您只需为不同数量的参数添加任意数量的部分特化:

template<class Fty>
struct result_of;

template<class F>
struct result_of<F()>{ /*...*/ };

template<class F, class A0>
struct result_of<F(A0)>{ /*...*/ };

template<class F, class A0, class A1>
struct result_of<F(A0, A1)>{ /*...*/ };

// ...

在C ++ 03中执行此操作的唯一其他方法是默认模板参数,并且对于每种情况都部分特殊 - 缺点是它看起来不再像函数调用,并且任何类型的包装器都使用{ {1}}内部不能只传递result_of


现在,功能类型方式有一个缺点 - 您还可以完成对“参数”的所有常规转换:Sig - &gt; R(Args...),更重要的是R(*)(Args...) - &gt; T[N]和顶级cv限定符被丢弃(T*):

§8.3.5/5

Live example.输出:

  

错误:静态断言失败:/ cry

其他问题是顶级cv限定符被丢弃:

struct X{
  bool operator()(int (&&arr)[3]);
  long operator()(void*);
};

static_assert(std::is_same<std::result_of<X(int[3])>::type, bool>(), "/cry");

Live example.输出:

  

错误:静态断言失败:/ cry

答案 1 :(得分:9)

我认为只是有人认为你可以(ab)使用函数类型表示法来模仿各个函子调用的样子,并且它会卡住。所以,没有技术原因,只是美学原因。

// the result type of a call to (an object of) type F,
// passing (objects of) types A, B, and C as parameters.
result_of<F(A, B, C)>::type

答案 2 :(得分:4)

result_of是TR1的一部分,它在将decltype添加到语言之前出现。但它的设计考虑了decltype,因此将result_of的实现更改为使用decltype很简单。是的,这是一个黑客,但它的确有效。

答案 3 :(得分:2)

(这会扩展到JohannesD's answerJesse Good's comment,但这不适用于评论。请注意其他答案不是这个。)

来自N1454 Syntax and examples

  

result_of行为的定义很简单:给定类型FT1T2,...,TN和左值{{这些类型分别为1}},ft1,...,t2,类型表达式

tN
  

计算表达式result_of<F(T1, T2, ..., TN)>::type 的类型。

这不是滥用类型系统,它非常优雅!