【问题标题】:Partial ordering rules of template parameter pack in C++17C++17模板参数包部分排序规则
【发布时间】:2021-08-02 16:53:41
【问题描述】:

这是来自temp.deduct.partial 的示例。

template<class... Args>           void f(Args... args);         // #1
template<class T1, class... Args> void f(T1 a1, Args... args);  // #2
template<class T1, class T2>      void f(T1 a1, T2 a2);         // #3

f();                // calls #1
f(1, 2, 3);         // calls #2
f(1, 2);            // calls #3; non-variadic template #3 is more specialized
                    // than the variadic templates #1 and #2

为什么f(1, 2, 3) 调用#2

CWG1395之前很容易理解。 #2 不能从#1 推导出来,因为Args 是一个参数包而T1 不是,所以#2#1 更专业。

但是在CWG1395之后如何理解这个例子呢?现在看来T1可以从Args推导出来了。

同样,如果A是从函数参数包转换而来的,它会与参数模板的每个剩余参数类型进行比较。

【问题讨论】:

    标签: c++ templates c++17 language-lawyer


    【解决方案1】:

    CWG1395 似乎没有更改与您从标准中引用的示例相关的任何内容。请记住,发布 CWG1935 是为了允许例如

        template<class T>
        void print(ostream &os, const T &t) {
            os << t;
        }
    
        template <class T, class... Args>
        void print(ostream &os, const T &t, const Args&... rest) {
            os << t << ", ";
            print(os, rest...);
        }
    
        int main() {
            print(cout, 42);
            print(cout, 42, 1.23);
        }
    

    在发布 1395 之前,来自调用 print(os, rest...) 的参数包扩展永远无法与 void print(ostream &amp;os, const T &amp;t) 的模板参数 T 匹配,因为函数参数包必须明确与模板参数包匹配:

    如果 A 是从函数参数包转换而来的,而 P 不是参数包,则类型推导失败。

    随着更改,现在允许第一个 print 函数与函数参数包调用匹配,并且被认为比 13.10.3.5 [temp.deduct.partial] 第 10 段的第二个重载更专业:

    如果在考虑了上述之后,函数模板 F 至少与函数模板 G 一样特化,反之亦然,并且如果 G 有一个尾随参数包,而 F 没有对应的参数,并且如果 F 没有有一个尾随参数包,则 F 比 G 更专业。

    但是,您上面的示例与函数参数包无关,因此不受更改的影响,因此[temp.deduct.type]/13.10.3.6 §10 的规则仍然适用。

    【讨论】:

      猜你喜欢
      • 2016-01-30
      • 2019-12-25
      • 1970-01-01
      • 2017-04-24
      • 1970-01-01
      • 1970-01-01
      • 2015-11-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多