考虑以下代码:
#include <tuple>
#include <iostream>
template <class T>
struct custom_wrapper
{
template <class Arg>
custom_wrapper(Arg arg): data(arg) {}
T data;
};
template <class Arg>
custom_wrapper(Arg arg) -> custom_wrapper<Arg>;
template <class... T>
struct custom_tuple
{
template <class... Args>
custom_tuple(Args... args): data(args...) {}
std::tuple<T...> data;
};
template <class... Args>
custom_tuple(Args... args) -> custom_tuple<Args...>;
int main(int argc, char* argv[])
{
custom_wrapper<int> w1(42); // OK
custom_wrapper w2(42); // OK
custom_tuple<int> t1(42); // OK
custom_tuple t2(42); // Fails
return 0;
}
失败的行在g++7下返回如下错误:
variadic_deduction_guide.cpp: In instantiation of 'custom_tuple<T>::custom_tuple(Args ...) [with Args = {int}; T = {}]':
variadic_deduction_guide.cpp:31:23: required from here
variadic_deduction_guide.cpp:19:45: error: no matching function for call to 'std::tuple<>::tuple(int&)'
custom_tuple(Args... args): data(args...) {}
这是正常现象还是编译器错误?
最佳答案
这是 gcc bug 80871 .下面是对为什么代码格式正确的解释(并且 clang 决定 t2
是 custom_tuple<int>
是正确的)。
弄清楚要做什么的过程
custom_tuple t2(42);
基本上涉及合成一堆函数并对它们执行重载解析。相关候选者是来自一个构造函数和推导指南的综合函数:
template <class... T, class... Args>
custom_tuple<T...> foo(Args... ); // the constructor
template <class... Args>
custom_tuple<Args...> foo(Args... ); // the deduction guide
从这一点开始,根据您对“尾随参数包”的解释来选择您自己的冒险 [temp.arg.explicit]/3 :
A trailing template parameter pack not otherwise deduced will be deduced to an empty sequence of template arguments. If all of the template arguments can be deduced, they may all be omitted; in this case, the empty template argument list
<>
itself may also be omitted.
T...
不尾随
这个案例很简单。我们只有一个可行的候选者(因为 T...
不可推导)——演绎指南候选者。我们推断Args...
作为{int}
, 所以我们最终得到 custom_tuple<int>
.
T...
尾随
gcc 和 clang 实际上确实考虑了构造函数的推导成功。所以我们进入决胜局 [over.match.best] :
Given these definitions, a viable function
F1
is defined to be a better function than another viable functionF2
if [...]
F1
andF2
are function template specializations, and the function template forF1
is more specialized than the template forF2
according to the partial ordering rules described in [temp.func.order], or, if not that,F1
is generated from a deduction-guide ([over.match.class.deduct]) andF2
is not, or, if not that, [...]
为了部分排序的目的,relevant types只是那些对应于函数参数的,我们被允许ignore unused template parameters , 因此没有一个函数模板被认为比另一个更专业。
这让我们更喜欢演绎指南,这是整个过程中最简单的步骤。我们推断Args...
作为{int}
, 所以我们最终得到 custom_tuple<int>
.
无论哪种方式,custom_tuple<int>
是正确的决定。
关于c++ - 演绎指南和可变参数模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50200044/