c – 模糊重载 – 使用参数包进行部分功能模板排序

考虑下列代码
template <class... > struct pack { };

template <class R,class T,class... Args>
int foo(pack<T>,Args...)
{
    return sizeof(R);
}

template <class R,class... Ts,class... Args>
int foo(pack<T,Ts...>,Args... args)
{
    return foo<T>(pack<Ts...>{},args...);
}

int main() {
    // gcc: OK,clang: ambiguous
    foo<int>(pack<int>{});

    // gcc: ambiguous,clang: ambiguous
    foo<int>(pack<int>{},0);
}

如果第二个重载更改为至少包含两个类型,而不是至少一个类型的包,则gcc和clang均可接受两个调用

template <class R,class T2,T2,Args... args)
{
    return foo<T>(pack<T2,Ts...>{},args...);
}

如果未推导的模板参数被移动到推导的模板参数,则:

template <class... > struct pack { };

template <class R,class... Args>
int foo(pack<R>,pack<T>,pack<T,Args... args)
{
    return foo(pack<T>{},pack<Ts...>{},args...);
}

int main() {
    // gcc ok with both,clang rejects both as ambiguous
    foo(pack<int>{},pack<int>{});
    foo(pack<int>{},pack<int>{},0);
}

我希望所有的电话都可以在每个版本的这个.上述代码示例的预期结果是什么?

解决方法

我相信现在cl声是正确的拒绝,gcc是不正确的接受它所做的那些形式.这是一个简化的例子:
template <class...> struct pack { };

// (1)
template <class T>
void foo(pack<T> ) { }

// (2)
template <class T,class... Ts>
void foo(pack<T,Ts...> ) { }

int main() {
    foo(pack<int>{});
}

两个过载都是有效的,(1)的推导(2)直接成功.唯一的问题是我们可以从(2)推导出(1).我最初不认为…但是[temp.deduct.type] / 9状态:

If P has a form that contains <T> or <i>,then each argument Pi of the respective template argument list of P is compared with the corresponding argument Ai of the corresponding template argument list of A. […] During partial ordering (14.8.2.4),if Ai was originally a pack expansion:
— if P does not contain a template argument corresponding to Ai then Ai is ignored;

@H_301_58@

所以当我们合成< T,Ts ...> (说< U,Xs ...>),我们推导出T = U,然后没有与包装Xs …对应的模板参数,所以我们忽略它.所有不被忽略的模板参数成功地进行模板推导,所以我们考虑从(2)推导出(1)成功.

由于扣除在双向成功,功能模板被认为比其他模板更专业,而且呼叫应该是模糊的.

我还没有提交错误报告,等待社区的一些确认.

相关文章

/** C+⬑ * 默认成员函数 原来C++类中,有6个默认成员函数: 构造函数 析构函数 拷贝...
#pragma once // 1. 设计一个不能被拷贝的类/* 解析:拷贝只会放生在两个场景中:拷贝构造函数以及赋值运...
C类型转换 C语言:显式和隐式类型转换 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译...
//异常的概念/*抛出异常后必须要捕获,否则终止程序(到最外层后会交给main管理,main的行为就是终止) try...
#pragma once /*Smart pointer 智能指针;灵巧指针 智能指针三大件//1.RAII//2.像指针一样使用//3.拷贝问...
目录&lt;future&gt;future模板类成员函数:promise类promise的使用例程:packaged_task模板类例程...