Ben*_*y K 10 c++ metaprogramming
我正在尝试从可变参数类型列表中提取类型的前缀。这是我的尝试:
#include <tuple>
#include <type_traits>
template <typename... Ts>
struct pack{};
template <size_t n, typename... Args>
struct prefix_tuple;
template <size_t n, typename... TPrefix, typename Tnext, typename... Ts>
struct prefix_tuple<n, pack<TPrefix...>, Tnext, Ts...>{
using type = typename
prefix_tuple<n-1, pack<TPrefix..., Tnext>, Ts...>::type;
};
template <typename... TPrefix, typename... Ts>
struct prefix_tuple<0, pack<TPrefix...>, Ts...>{
using type = std::tuple<TPrefix...>;
};
template <size_t n, typename... Args>
using prefix_tuple_t = typename
prefix_tuple<n, pack<>, Args...>::type;
bool f(){
return std::is_same_v<prefix_tuple_t<2, int, char, double>,
std::tuple<int, char> >;
}
Run Code Online (Sandbox Code Playgroud)
这在gcc 8.2上失败,原因是:
错误:“结构prefix_tuple <0,pack <int,char>,double>”的模板实例化不明确
第二个专业似乎比第一个专业更具体,所以我不明白为什么这里有歧义。我究竟做错了什么?
PS这在clang 7.0上也失败,并显示类似错误,但在icc 19.0.1和msvc 19.16上似乎可以使用。
经过更多研究,以下是我的发现:
这些是部分排序规则:
1) 如果只有一种特化与模板参数匹配,则使用该特化。
2) 如果多个专业化匹配,则使用偏序规则来确定哪个专业化更专业。如果唯一,则使用最专业的特化(如果不唯一,则程序无法编译)。
3) 如果没有专业匹配,则使用主模板
和:
通俗地说,“ A比B更专业”意味着“ A接受B接受的类型的子集”。
令A和B分别为我的代码中的第一个和第二个专业化。
An接受数字大于 0的结构( B不接受)。另一方面,B接受前缀包后面带有 0 类型的结构(A不接受)。因此,A和B都不是“最专业的”,并且该程序不应编译。也就是icc和msvc是错误的。
假设我添加了我的评论中提到的以下第三个专业化(称为C):
template <typename... TPrefix, typename Tnext, typename... Ts>
struct prefix_tuple<0, pack<TPrefix...>, Tnext, Ts...>{
using type = std::tuple<TPrefix...>;
};
Run Code Online (Sandbox Code Playgroud)
C不接受n大于 0 的数字,也不接受前缀包后面带有 0 类型的结构。因此它是最专业的。此外, ifn==0和C不能使用,A也不能使用,因此这解决了A和B之间的歧义。
添加此内容后,代码可以与 gcc、clang 和 msvc 一起使用,但 icc 拒绝它并出现以下错误:
错误:多个部分特化
与类“prefix_tuple<0UL, pack < int, char >, double>”的模板参数列表匹配:
“prefix_tuple<0UL, pack < TPrefix...>, Tnext, Ts...> "
"prefix_tuple<0UL, pack < TPrefix...>, Ts...>"
正如我之前提到的,其中第一个(C )比第二个( B )更专业,所以我必须再次推断出 icc 是错误的。
| 归档时间: |
|
| 查看次数: |
144 次 |
| 最近记录: |