这是编译器错误还是程序员错误?

时间:2012-03-23 18:41:49

标签: c++ c++11 clang variadic-templates

我正在使用元组作为编译时间列表。在How can I have multiple parameter packs in a variadic template?我用一些在GCC和Clang中都有效的代码回答了自己,但Clang现在不会编译我已添加(我认为是)完美转发。它抱怨As...as...std::forward<As>(as)...中的长度不同。当As...as...的类型时,如何才能成立?参数中的As&&... as

#include <iostream>
#include <tuple>

template < typename ... >
struct two_impl {};

// Base case
template < typename F,
           typename ...Bs >
struct two_impl < F, std::tuple <>, std::tuple< Bs... > >  {
  void operator()(F&& f, Bs&&... bs) {
    f(std::forward<Bs>(bs)...);
  }
};

// Recursive case
template < typename F,
           typename A,
           typename ...As,
           typename ...Bs >
struct two_impl < F, std::tuple< A, As... >, std::tuple< Bs...> >  {
  void operator()(F&& f, A&& a, As&&... as, Bs&&... bs) {
    auto impl = two_impl < F, std::tuple < As&&... >, std::tuple < Bs&&..., A&& > >();
    impl(std::forward<F>(f), std::forward<As>(as)..., std::forward<Bs>(bs)..., std::forward<A>(a));
  }
};

template < typename F, typename ...Ts >
void two(F&& f, Ts&& ...ts) {
  auto impl = two_impl< F, std::tuple < Ts... >, std::tuple <> >();
  impl(std::forward<F>(f), std::forward<Ts>(ts)...);
}

struct Test {
  void operator()(int i, float f, double d) {
    std::cout << i << std::endl << f << std::endl << d << std::endl;
  }
};

int main () {
  two(Test(), 1, 1.5f, 2.1);
}

使用clang -lstdc++ -std=c++0x multiple_parameter_packs.cpp

进行编译
clang -lstdc++ -std=c++0x multiple_parameter_packs.cpp 
multiple_parameter_packs.cpp:24:50: error: pack expansion contains parameter packs 'As' and 'as' that have different
      lengths (1 vs. 2)
    impl(std::forward<F>(f), std::forward<As>(as)..., std::forward<Bs>(bs)..., std::forward<A>(a));
                                          ~~  ~~ ^
multiple_parameter_packs.cpp:24:5: note: in instantiation of member function 'two_impl<Test, std::tuple<float &&,
      double &&>, std::tuple<int &&> >::operator()' requested here
    impl(std::forward<F>(f), std::forward<As>(as)..., std::forward<Bs>(bs)..., std::forward<A>(a));
    ^
multiple_parameter_packs.cpp:31:3: note: in instantiation of member function 'two_impl<Test, std::tuple<int, float,
      double>, std::tuple<> >::operator()' requested here
  impl(std::forward<F>(f), std::forward<Ts>(ts)...);
  ^
multiple_parameter_packs.cpp:41:3: note: in instantiation of function template specialization
      'two<Test, int, float, double>' requested here
  two(Test(), 1, 1.5f, 2.1);
  ^
1 error generated.

Compilation exited abnormally with code 1 at Fri Mar 23 14:25:14

2 个答案:

答案 0 :(得分:3)

这似乎是旧版Clang中的一个错误。该代码适用于trunk Clang,可以使用libstdc ++或libc ++。

$ clang++ multiple_parameter_packs.cpp -std=c++11 -stdlib=libc++
$ ./a.out
1
1.5
2.1

答案 1 :(得分:1)

我不认为这个:

void operator()(F&& f, A&& a, As&&... as, Bs&&... bs)

很有可能。

参数包应该是最后一个参数,As&&... as后面跟着另一个包。