4

问题来自这里- 我想创建一种解决更普遍问题的方法。考虑一个例子:

#include <utility>

template<class T, std::size_t>
using deduced = T;

template<std::size_t N, class = std::make_index_sequence<N>>
struct Foo;

template<std::size_t N, std::size_t... Is>
struct Foo<N, std::index_sequence<Is...>>{
    template <class... Args>
    void Bar(deduced<Args, Is>...)
    {  }
};

int main() {
   Foo<3> myfoo;
   myfoo.Bar(true, 2.0f, 3); // OK
   //myfoo.Bar(1, 2, 3, 4); // error
}

clang 编译代码没有问题,另一方面 gcc 显示以下错误:

prog.cc: In function 'int main()':
prog.cc:18:27: error: no matching function for call to 'Foo<3ul>::Bar(bool, float, int)'
    myfoo.Bar(true, 2.0f, 3); // valid
                           ^
prog.cc:12:10: note: candidate: template<class ... Args> void Foo<N, std::integer_sequence<long unsigned int, Is ...> >::Bar(deduced<Args, Is>...) [with Args = {Args ...}; long unsigned int N = 3ul; long unsigned int ...Is = {0ul, 1ul, 2ul}]
     void Bar(deduced<Args, Is>...)
          ^~~
prog.cc:12:10: note:   template argument deduction/substitution failed:
prog.cc:18: confused by earlier errors, bailing out

[现场演示]

让我感到困惑的是 gcc 在使用相同的别名但不涉及外部参数包时没有扣除问题,例如:

void Bar(deduced<Args, 0>...)

所以问题是 - 将外部类和内部类的参数包与这种形式的别名结合起来以使编译器推断出模板参数之一是否合法,还是 gcc 错误?

编辑(基于博格丹的评论)

该代码也会给 MSVC (2017 RC) 带来麻烦,但以这种形式与 EDG 编译器一起工作,icc(版本 16 和 17)似乎也能很好地处理代码。还值得注意的是,使用类而不是别名的类似代码(在某些地方也被视为推断的上下文,例如 bogdan)会给编译器带来更多麻烦——只有 clang 似乎可以很好地处理这个版本(?)

4

0 回答 0