避免模棱两可的部分专业化
Avoid ambiguous partial specialization
我有以下模板:
template<typename T, typename S=void>
struct Array;
template<typename T, int N0, int N1, int S0, int S1>
struct Array<T[N0][N1], T[S0][S1]> {};
template<typename T, int N0, int N1>
struct Array<T[N0][N1], void> : Array<T[N0][N1], T[N1][1]> {};
template<typename T, int N0, int N1, int N2, int S0, int S1, int S2>
struct Array<T[N0][N1][N2], T[S0][S1][S2]> {
template<int B0, int E0, int B1, int E1, int B2, int E2>
Array<T[E0 - B0][E1 - B1][E2 - B2], T[S0][S1][S2]>
get() {
return Array<T[E0 - B0][E1 - B1][E2 - B2], T[S0][S1][S2]>();
}
};
template<typename T, int N0, int N1, int N2>
struct Array<T[N0][N1][N2], void> : Array<T[N0][N1][N2], T[N1 * N2][N2][1]> {};
int main() {
Array<float[3][4][4], float[16][4][1]> a;
auto b = a.get<0, 2, 0, 2, 0, 1>();
return 0;
}
由于模板的部分专业化不明确,我得到了以下错误:
$ clang++ -std=c++11 main.cpp && ./a.out
main.cpp:26:14: error: ambiguous partial specializations of 'Array<float [2][2][1], float [16][4][1]>'
auto b = a.get<0, 2, 0, 2, 0, 1>();
^
main.cpp:5:8: note: partial specialization matches [with T = float [1], N0 = 2, N1 = 2, S0 = 16, S1 = 4]
struct Array<T[N0][N1], T[S0][S1]> {};
^
main.cpp:11:8: note: partial specialization matches [with T = float, N0 = 2, N1 = 2, N2 = 1, S0 = 16, S1 = 4, S2 = 1]
struct Array<T[N0][N1][N2], T[S0][S1][S2]> {
^
1 error generated.
有什么方法可以避免这种歧义吗?换句话说,我希望只有当T是非数组类型时,数组模板才有效。
这可能有些过头了,但您可以强制T
不是数组:
#include <type_traits>
template<typename T, typename S = void, typename Dummy = void>
struct Array;
template<typename T, int N0, int N1, int S0, int S1>
struct Array<T[N0][N1],
T[S0][S1],
typename std::enable_if<!std::is_array<T>::value>::type>
{ };
template<typename T, int N0, int N1>
struct Array<T[N0][N1],
void,
typename std::enable_if<!std::is_array<T>::value>::type>
: Array<T[N0][N1], T[N1][1]>
{ };
template<typename T, int N0, int N1, int N2, int S0, int S1, int S2>
struct Array<T[N0][N1][N2],
T[S0][S1][S2],
typename std::enable_if<!std::is_array<T>::value>::type>
{
template<int B0, int E0, int B1, int E1, int B2, int E2>
Array<T[E0 - B0][E1 - B1][E2 - B2], T[S0][S1][S2]>
get()
{
return {};
}
};
如果您真的想允许T
使用数组类型,那么还需要进一步研究。
相关文章:
- 如何使用默认参数等选择模板专业化
- 模板化建造师专业化
- 类模板的成员功能的定义在单独的TU中完全专业化
- 部分专业化和嵌套模板
- 模板专业化可以进入我的.cpp吗?
- "Inverse SFINAE"避免模棱两可的过载
- 别名模板的专业化 C++11 中没有开销的最佳替代方案
- 操作员C++的模棱两可的过载
- 模棱两可的重载模板
- 部分专业化和对标准::void_t<>的需求
- 调用重载的"<大括号括起来的初始值设定项列表>"对于对来说就足够了是模棱两可的
- "专业化不参与超载"
- 特定好友功能专业化
- 是否可以混合使用SFINAE和模板专业化?
- 模棱两可的 != reverse_iterator运算符
- SFINAE不能防止模棱两可的操作员过载吗?
- VSCode 说 std::chrono 是模棱两可的,如果运算符<<重载
- C++17 年与 Clang 的模棱两可的部分专业化
- 模棱两可的部分专业化取决于std :: enable_if
- 避免模棱两可的部分专业化