我遇到的问题是来自clang(c ++ 14)的以下警告:
包扩展包含参数包'v_seconds',它与外部参数包具有不同的长度(3对1)
以下示例代码中遇到此问题:
template<typename... v_firsts>
struct types_list {
template<typename... v_seconds>
using pairs_list = types_list<std::pair<v_firsts, v_seconds>...>;
};
using my_types_list = types_list<short, int, long>;
using my_pairs_list = my_types_list::pairs_list<short, int, long>; // GOOD
template<typename... v_pack>
using any_pairs_list = my_types_list::pairs_list<v_pack...>; // BAD
我如何解释错误是以某种方式遇到any_pairs_list
的{{1}}长度为1的特化,然后自然会遇到错误。
然而,上面的代码是整个示例代码 - 我从不使用v_seconds
的专业化。
所以,我必须得出结论,尽管仍然创造了专业化......
现在,通常的TMP分叉问题:
any_pairs_list
P.S。我已经使用Apple安装的Clang(v8.1.0)以及Visual Studio 2017 Clang扩展进行了测试。不幸的是我没有linux环境来测试...
答案 0 :(得分:2)
我最好的猜测是,Clang使用某种类型的启发式方法来检查固有的不可实现的模板。也许它(虚假地)决定any_pairs_list
中的别名有一个参数,因为它没有正确处理包扩展,然后用一些独特的合成类型代替它来测试它是否原则上可行。毕竟,如果您不使用包但只使用一个沼泽标准模板参数,则会收到完全相同的错误消息。
报告为#32905。
答案 1 :(得分:0)
不是解决方案,而是解决方法。使pairs_list
成为名为成员typedef的结构,例如type
。由于这是有效的,我会说这是Clang中using
别名模板中的一个错误。
#include <iostream>
#include <utility>
template<typename... v_firsts>
struct types_list {
template<typename... v_seconds>
struct pairs_list {
typedef types_list<std::pair<v_firsts, v_seconds>...> type;
};
};
using my_types_list = types_list<short, int, long>;
using my_pairs_list = my_types_list::pairs_list<short, int, long>::type;
template<typename... v_pack>
using any_pairs_list = typename my_types_list::pairs_list<v_pack...>::type;
// Let's see what has been deduced
template < typename T >
void show_signature() { std::cout << __PRETTY_FUNCTION__ << '\n'; }
int main() {
show_signature<my_types_list>(); // T = types_list<short, int, long>
show_signature<my_pairs_list>(); // T = types_list<std::pair<short, short>, std::pair<int, int>, std::pair<long, long> >
show_signature<any_pairs_list<int,long,double>>(); // T = types_list<std::pair<short, int>, std::pair<int, long>, std::pair<long, double> >
}