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

Ste*_*Lin 18 c++ boost std c++11

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

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

template< class F, class... ArgTypes >
class result_of<F(ArgTypes...)>;
Run Code Online (Sandbox Code Playgroud)

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

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

template< class F, class... ArgTypes >
class result_of<F, ArgTypes...>;
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • C++ 11委员会是否有任何关于如何将其标准化的讨论,因为无论如何std::result_of都可以decltype相当容易地实现?

Xeo*_*Xeo 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)>{ /*...*/ };

// ...
Run Code Online (Sandbox Code Playgroud)

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


现在,函数类型方式有一个缺点 - 你也可以完成对"参数"的所有常规转换:R(Args...)- > R(*)(Args...)更重要的是T[N]- > T*和顶级cv限定符被丢弃(§8.3.5/5):

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

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

实例.输出:

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

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

struct Y{};

struct X{
  bool operator()(Y const&);
  long operator()(Y&&);
};

Y const f();

static_assert(std::is_same<std::result_of<X(Y const)>::type, bool>(), "/cry");
Run Code Online (Sandbox Code Playgroud)

实例.输出:

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


Joh*_*esD 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
Run Code Online (Sandbox Code Playgroud)

  • +1 [这里的理由]中也提到了这一点(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1454.html). (2认同)