Class 派生的 class 模板参数推导失败

Class template argument deduction failed with derived class

#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
}

上面的格式是否正确?

如果构造函数被继承,是否可以在第二种情况下推导出 class 模板参数? std::pair 的构造函数是否参与了 ​​mypair 的隐式推导指南的创建?

我的编译器是 g++ 7.2.0。

参见


此答案的先前版本指出以下应该有效

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

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

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

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

原则上,可能有一条规则说在这种情况下您要查看主 pair 模板的构造函数(就像我们在查找 mypair 本身的构造函数时所做的一样class template argument deduction),但目前标准中实际上没有这样的规则。但是,当基础 class 变得更加复杂时,这样的规则很快就会失效:

template<typename T> struct my_pair2 : std::pair<T, T> {
  using pair::pair;
};

理论上应该在此处注入哪些构造函数?在这种情况下,我认为很明显这种查找不可能起作用:

template<typename T> struct my_pair3 : arbitrary_metafunction<T>::type {
  using arbitrary_metafunction<T>::type::type;
};

我们可能会更改规则以允许通过您的 my_pair 和 if/when 上面的 my_pair2 进行推导,我们得到 class 别名的模板参数推导规则模板:

template<typename T> using my_pair3 = std::pair<T, T>;
my_pair3 mp3 = {1, 2};

这里涉及的复杂性在很大程度上与继承构造函数的情况相同。 Faisal Vali(class 模板参数推导的其他设计者之一)有一个关于如何使这种情况起作用的具体计划,但 C++ 委员会尚未讨论此扩展​​。