<可变参数模板> 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
特征来提取模板类的第一个参数,其中从第二个模板参数开始具有默认值(例如,实际用例是std::unique_ptr
)。Clang和GCC完美地处理了这个片段,但是MSVC(Visual Studio 17附带的那个)抛出了非常不明显的编译错误。
事实证明,GCC 和 Clang 以某种方式处理默认模板参数,以便<template <typename...> typename Bar, typename X> Bar<X>
接口接受A<X, Y=void>
。另一方面,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;
}
从编译器错误中理解问题真的很难,我无法用谷歌搜索出解决方案,这就是我想分享我的原因。
相关文章:
- 当给定默认值时,为什么此模板参数推导失败
- 如何在C++中提供模板化函数作为另一个函数的参数,默认值?
- 在 c++ 中,如果我创建一个接受一个具有默认值的参数的构造函数 - 它会用作默认(空)构造函数吗?
- 为什么无法在可变参数模板中将尾随模板参数指定为默认值?
- 可变参数模板和具有继承的默认值
- 具有默认值的单个参数构造函数是否与默认构造函数相同?
- 在子类函数覆盖中省略具有默认值的参数
- 函数作为具有默认值的参数
- 具有另一个具有默认值的模板参数的模板推导
- const变量是否可以在具有默认值的参数中赋值(作为可选参数)
- 可以通过常量引用返回默认参数的值吗?
- 对 const 引用参数使用默认值会导致崩溃
- C ,构造器中允许的参考参数默认值
- 是否可以设计一个包含模板参数默认值的类
- 构造函数中参数C++默认值
- 如何设置依赖于其他参数的参数默认值
- QInput对话框参数默认值
- 在函数定义中指定参数默认值会导致错误 C2143:语法错误:'='之前缺少')'
- 内置类型的模板参数默认值
- 是否可以使用构造函数或对象作为其他类方法的参数默认值?