<variadic template> Visual Studio 中具有默认值编译错误的模板参数
<variadic template> template parameters with default value compilation error in Visual Studio
在将代码从 GCC 移植到 MSVC 时遇到这个难解的问题。
考虑以下片段:
template <typename T>
struct Foo;
template <template <typename...> typename Container, typename Arg>
struct Foo<Container<Arg>> {
using arg_t = Arg;
};
template <typename X>
struct A {};
template <typename X, typename Y = void>
struct B {};
template <typename X, typename Y = void, typename Z = void>
struct C {};
int main() {
typename Foo<A<int>>::arg_t a;
typename Foo<B<int>>::arg_t b;
typename Foo<C<int>>::arg_t c;
return 0;
}
我们使用 Foo
特征来提取模板的第一个参数 class,其中从第二个模板参数开始有默认值(例如,实际用例是 std::unique_ptr
) . Clang 和 GCC 完美地处理了这个片段,但是 MSVC(Visual Studio 17 附带的那个)抛出非常不明显的编译错误。
事实证明,GCC 和 Clang 以某种方式处理默认模板参数,因此 A<X, Y=void>
被 <template <typename...> typename Bar, typename X> Bar<X>
接口接受。另一方面,MSVC 没有。不确定它是标准的还是 GCC/Clang 扩展。
无论如何,解决方案是添加虚拟可变参数以匹配剩余参数。
template <typename T>
struct Foo;
template <template <typename...> typename Container,
typename Arg, typename... MsvcWorkaround>
struct Foo<Container<Arg, MsvcWorkaround....>> {
using arg_t = Arg;
};
template <typename X>
struct A {};
template <typename X, typename Y = void>
struct B {};
template <typename X, typename Y = void, typename Z = void>
struct C {};
int main() {
typename Foo<A<int>>::arg_t a;
typename Foo<B<int>>::arg_t b;
typename Foo<C<int>>::arg_t c;
return 0;
}
很难从编译器错误中理解问题,我无法 google 找到解决方案,这就是为什么我想分享我的。
在将代码从 GCC 移植到 MSVC 时遇到这个难解的问题。
考虑以下片段:
template <typename T>
struct Foo;
template <template <typename...> typename Container, typename Arg>
struct Foo<Container<Arg>> {
using arg_t = Arg;
};
template <typename X>
struct A {};
template <typename X, typename Y = void>
struct B {};
template <typename X, typename Y = void, typename Z = void>
struct C {};
int main() {
typename Foo<A<int>>::arg_t a;
typename Foo<B<int>>::arg_t b;
typename Foo<C<int>>::arg_t c;
return 0;
}
我们使用 Foo
特征来提取模板的第一个参数 class,其中从第二个模板参数开始有默认值(例如,实际用例是 std::unique_ptr
) . Clang 和 GCC 完美地处理了这个片段,但是 MSVC(Visual Studio 17 附带的那个)抛出非常不明显的编译错误。
事实证明,GCC 和 Clang 以某种方式处理默认模板参数,因此 A<X, Y=void>
被 <template <typename...> typename Bar, typename X> Bar<X>
接口接受。另一方面,MSVC 没有。不确定它是标准的还是 GCC/Clang 扩展。
无论如何,解决方案是添加虚拟可变参数以匹配剩余参数。
template <typename T>
struct Foo;
template <template <typename...> typename Container,
typename Arg, typename... MsvcWorkaround>
struct Foo<Container<Arg, MsvcWorkaround....>> {
using arg_t = Arg;
};
template <typename X>
struct A {};
template <typename X, typename Y = void>
struct B {};
template <typename X, typename Y = void, typename Z = void>
struct C {};
int main() {
typename Foo<A<int>>::arg_t a;
typename Foo<B<int>>::arg_t b;
typename Foo<C<int>>::arg_t c;
return 0;
}
很难从编译器错误中理解问题,我无法 google 找到解决方案,这就是为什么我想分享我的。