类模板参数推导因派生类而失败

Per*_*-lk 14 c++ templates g++ template-argument-deduction c++17

#include <utility>

template<class T1, class T2>
struct mypair : std::pair<T1, T2>
{ using std::pair<T1, T2>::pair; };

int main()
{
    (void)std::pair(2, 3); // It works
    (void)mypair(2, 3);    // It doesn't work
}
Run Code Online (Sandbox Code Playgroud)

以上是否形成良好?

如果继承构造函数,是否可能在第二种情况下推导出类模板参数?构建者是否std::pair参与创建隐式演绎指南mypair

我的编译器是g ++ 7.2.0.

Ric*_*ith 11

简短的故事:标准中没有规定这将如何工作,也没有任何规定说它不起作用。所以 GCC 和 Clang 保守地拒绝而不是发明一个(非标准)规则。

长话短说: mypairpair基类是依赖类型,因此无法成功查找其构造函数。对于每个专业化mytype<T1, T2>,相应构造pair<T1, T2>是构造mytype,但是这不是可以有意义施加到模板实例之前在一般的规则。

原则上,可能有一条规则说pair在这种情况下您查看主模板的构造函数(就像我们在查找mypair自身的构造函数以进行类模板参数推导时所做的一样),但标准中实际上不存在这样的规则目前。然而,当基类变得更加复杂时,这样的规则很快就会失效:

template<typename T> struct my_pair2 : std::pair<T, T> {
  using pair::pair;
};
Run Code Online (Sandbox Code Playgroud)

什么构造函数应该在这里注入?在这种情况下,我认为很明显这种查找不可能工作:

template<typename T> struct my_pair3 : arbitrary_metafunction<T>::type {
  using arbitrary_metafunction<T>::type::type;
};
Run Code Online (Sandbox Code Playgroud)

如果/当我们获得别名模板的类模板参数推导规则时,我们可能会更改规则以允许通过您的my_pairmy_pair2上述推导进行推导:

template<typename T> using my_pair3 = std::pair<T, T>;
my_pair3 mp3 = {1, 2};
Run Code Online (Sandbox Code Playgroud)

这里涉及的复杂性与继承构造函数的情况大致相同。Faisal Vali(类模板参数推导的其他设计者之一)对于如何使这种情况起作用有一个具体的计划,但是 C++ 委员会还没有讨论这个扩展。


Bar*_*rry 8

理查德史密斯的回答


此答案的先前版本已声明以下内容应该有效

template <class T> struct B { B(T ) { } };
template <class T> struct D : B<T> { using B<T>::B; };

B b = 4; // okay, obviously
D d = 4; // expected: okay
Run Code Online (Sandbox Code Playgroud)

但这并不是真正可行的,甚至不是像我想象的那样工作的好主意(我们继承构造函数而不是推导指南?)

  • 我倾向于说这应该_不_工作。并且仅使用基类的构造函数而不使用其推导指南肯定是没有意义的。 (2认同)