c++ - 演绎指南和可变参数模板

标签 c++ g++ tuples c++17 template-argument-deduction

考虑以下代码:

#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 决定 t2custom_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 function F2 if [...]

  • F1 and F2 are function template specializations, and the function template for F1 is more specialized than the template for F2 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]) and F2 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/

相关文章:

C++ valarray 与 vector

c++ - 错误 C2236 : unexpected token 'enum'

gcc - 如何获取 gcc 和 g++ 的错误和警告计数?

list - 从 Haskell 中的元组列表中选择数据

swift - 具有单个元素的元组

c++ - 调用删除时 STL 迭代器失效的问题

c++ - 使用模板的嵌套类中的未知类型名称 'class'

c++ - G++未定义对类::函数的引用

c++ - malloc 错误“命名管道打开时内存损坏(快速)

dictionary - Julia : construct Dictionary with tuple values