Vin*_*ent 9 c++ tuples g++ template-argument-deduction c++17
请考虑以下代码:
#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;
}
Run Code Online (Sandbox Code Playgroud)
失败的行在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...) {}
Run Code Online (Sandbox Code Playgroud)
这是正常的还是编译器错误?
这是gcc 错误 80871。接下来是对为什么代码格式良好的解释(并且 clang 正确地判定它t2是 a custom_tuple<int>)。
弄清楚要做什么的过程
custom_tuple t2(42);
Run Code Online (Sandbox Code Playgroud)
基本上涉及合成一堆函数并对它们执行重载解析。相关候选者是来自一个构造函数和推导指南的综合函数:
template <class... T, class... Args>
custom_tuple<T...> foo(Args... ); // the constructor
template <class... Args>
custom_tuple<Args...> foo(Args... ); // the deduction guide
Run Code Online (Sandbox Code Playgroud)
从这一点开始,您可以根据[temp.arg.explicit]/3对“尾随参数包”的解释来选择您自己的冒险:
未以其他方式推导的尾随模板参数包将被推导为模板参数的空序列。如果所有模板实参都可以推导,则可以全部省略;在这种情况下,空模板参数列表
<>本身也可以被省略。
T...不落后
这个案子很简单。我们只有一个可行的候选者(因为T...不可推导)——演绎指南候选者。我们推论Args...为{int},所以我们最终得到custom_tuple<int>。
T...正在落后
gcc 和 clang 实际上都考虑了构造函数的成功演绎。所以我们进入[over.match.best]的决胜局:
给定这些定义,一个可行的函数
F1被定义为比另一个可行的函数更好的F2函数,如果 [...]
F1和F2是函数模板特化,并且根据 [temp.func.order] 中描述的部分排序规则, 函数F1模板比模板更特化,或者,如果不是这样,F2F1是从演绎指南([over.match.class.deduct])生成的,但F2不是,或者,如果不是,[...]
出于部分排序的目的,相关类型只是与函数参数相对应的类型,并且我们可以忽略未使用的模板参数,因此两个函数模板都不被认为比另一个更专业。
这让我们更喜欢演绎指南,这是整个过程中最简单的步骤。我们推论Args...为{int},所以我们最终得到custom_tuple<int>。
无论哪种方式,custom_tuple<int>都是正确的决定。
| 归档时间: |
|
| 查看次数: |
701 次 |
| 最近记录: |