使用来自外部 class 的可变参数模板的参数部分特化可变参数模板内部 class 是否合法
Is it legal to partially specialise variadic template inner class with args from variadic template of an outer class
考虑代码:
#include <iostream>
template <class... Ts>
struct outer {
template <class... ITs>
struct inner {
static constexpr bool value = false;
};
template <class... ITs>
struct inner<Ts..., ITs...> {
static constexpr bool value = true;
};
};
int main() {
std::cout << outer<int, float, double>::inner<int, float, double, int>::value << std::endl;
}
代码使用 clang++ 编译,但不使用 g++ 编译,它会产生错误:
temp3.cc:11:11: error: parameter pack argument ‘Ts ...’ must be at the
end of the template argument list
struct inner<Ts..., ITs...> {
^
正如我已经建立的 内部 class 的部分专业化应该是合法的。
编辑:
为了完整起见,值得补充的是,上述代码的 clang 警告他可能在推导 IT 参数时遇到问题但没有任何问题...
这是一个 gcc 错误。这是一个完全有效的偏特化:
template <class... ITs>
struct inner<Ts..., ITs...> {
static constexpr bool value = true;
};
推导的模板参数包必须在最后,ITs...
满足。但是Ts...
并不是这里需要推导的包,它只是一个特定的参数包。
此外,gcc 编译了几个等效的公式:
template <class... Ts>
struct X {
template <class... Us>
static void foo(Ts..., Us...) { }
};
int main() {
X<int>::foo(1, 'c');
}
和:
template <class... Us>
struct A { };
template <class... Ts>
struct X {
template <class... Us>
static void foo(A<Ts..., Us...>) { }
};
int main() {
X<int>::foo(A<int, char>{});
}
这些与您的原始示例等效。
受 Barry 回答启发的可能的简单而有效的解决方法:
#include <iostream>
template <class... Ts>
struct pack { };
template <class... Ts>
struct outer {
template <class IT>
struct inner {
static constexpr bool value = false;
};
template <class... ITs>
struct inner<pack<Ts..., ITs...>> {
static constexpr bool value = true;
};
};
int main() {
std::cout << outer<int, float, double>::inner<pack<int, float, double, int>>::value << std::endl;
}
(虽然它仍然在 clang 中产生警告)
基于 W.F. 的回答,仍然保持与原始问题相同的主要内容:
#include <iostream>
template <class... Ts>
struct pack { };
template <class... Ts>
class outer {
template <class IT>
struct _inner {
static constexpr bool value = false;
};
template <class... ITs>
struct _inner<pack<Ts..., ITs...>> {
static constexpr bool value = true;
};
public:
template <class... ITs>
struct inner {
static constexpr bool value = _inner<pack<ITs...>>::value;
};
};
int main() {
std::cout << outer<int, float, double>::inner<int, float, double, int>::value
<< std::endl;
}
它仍然在 clang 中产生警告,因为 _inner 的专用版本无法推断出 ITs... 除了 Ts...,ITs... 的列表(在 struct _inner<pack<Ts..., ITs...>>
中)- - 但是代码不需要从 Ts...,ITs... 列表中单独推导出 ITs,所以这应该没问题。
在 g++ 中编译时没有警告。
代码:http://coliru.stacked-crooked.com/a/ae3b21dd847450b2
(对于在 clang 中也没有警告的解决方案:http://coliru.stacked-crooked.com/a/0c6c643c8ff5809e)。
考虑代码:
#include <iostream>
template <class... Ts>
struct outer {
template <class... ITs>
struct inner {
static constexpr bool value = false;
};
template <class... ITs>
struct inner<Ts..., ITs...> {
static constexpr bool value = true;
};
};
int main() {
std::cout << outer<int, float, double>::inner<int, float, double, int>::value << std::endl;
}
代码使用 clang++ 编译,但不使用 g++ 编译,它会产生错误:
temp3.cc:11:11: error: parameter pack argument ‘Ts ...’ must be at the end of the template argument list
struct inner<Ts..., ITs...> { ^
正如我已经建立的
编辑: 为了完整起见,值得补充的是,上述代码的 clang 警告他可能在推导 IT 参数时遇到问题但没有任何问题...
这是一个 gcc 错误。这是一个完全有效的偏特化:
template <class... ITs>
struct inner<Ts..., ITs...> {
static constexpr bool value = true;
};
推导的模板参数包必须在最后,ITs...
满足。但是Ts...
并不是这里需要推导的包,它只是一个特定的参数包。
此外,gcc 编译了几个等效的公式:
template <class... Ts>
struct X {
template <class... Us>
static void foo(Ts..., Us...) { }
};
int main() {
X<int>::foo(1, 'c');
}
和:
template <class... Us>
struct A { };
template <class... Ts>
struct X {
template <class... Us>
static void foo(A<Ts..., Us...>) { }
};
int main() {
X<int>::foo(A<int, char>{});
}
这些与您的原始示例等效。
受 Barry 回答启发的可能的简单而有效的解决方法:
#include <iostream>
template <class... Ts>
struct pack { };
template <class... Ts>
struct outer {
template <class IT>
struct inner {
static constexpr bool value = false;
};
template <class... ITs>
struct inner<pack<Ts..., ITs...>> {
static constexpr bool value = true;
};
};
int main() {
std::cout << outer<int, float, double>::inner<pack<int, float, double, int>>::value << std::endl;
}
(虽然它仍然在 clang 中产生警告)
基于 W.F. 的回答,仍然保持与原始问题相同的主要内容:
#include <iostream>
template <class... Ts>
struct pack { };
template <class... Ts>
class outer {
template <class IT>
struct _inner {
static constexpr bool value = false;
};
template <class... ITs>
struct _inner<pack<Ts..., ITs...>> {
static constexpr bool value = true;
};
public:
template <class... ITs>
struct inner {
static constexpr bool value = _inner<pack<ITs...>>::value;
};
};
int main() {
std::cout << outer<int, float, double>::inner<int, float, double, int>::value
<< std::endl;
}
它仍然在 clang 中产生警告,因为 _inner 的专用版本无法推断出 ITs... 除了 Ts...,ITs... 的列表(在 struct _inner<pack<Ts..., ITs...>>
中)- - 但是代码不需要从 Ts...,ITs... 列表中单独推导出 ITs,所以这应该没问题。
在 g++ 中编译时没有警告。
代码:http://coliru.stacked-crooked.com/a/ae3b21dd847450b2
(对于在 clang 中也没有警告的解决方案:http://coliru.stacked-crooked.com/a/0c6c643c8ff5809e)。