Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ <;可变模板>;Visual Studio中具有默认值的模板参数编译错误_C++_Visual Studio_Templates_Variadic Templates_Template Templates - Fatal编程技术网

C++ <;可变模板>;Visual Studio中具有默认值的模板参数编译错误

C++ <;可变模板>;Visual Studio中具有默认值的模板参数编译错误,c++,visual-studio,templates,variadic-templates,template-templates,C++,Visual Studio,Templates,Variadic Templates,Template Templates,在将代码从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>

在将代码从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;
模板
结构Foo{
使用arg_t=arg;
};
模板
结构A{};
模板
结构B{};
模板
结构C{};
int main(){
typename Foo::arg\u t a;
类型名Foo::arg\u t b;
类型名Foo::arg\u t c;
返回0;
}

我们使用
Foo
trait来提取模板类的第一个参数,其中从第二个模板开始的参数具有默认值(例如,真正的用例是
std::unique_ptr
)。Clang和GCC完美地处理了这个代码段,但是MSVC(Visual Studio 17附带的一个)抛出了非常明显的编译错误。

结果是,GCC和Clang以某种方式处理了默认模板参数,因此
Bar
接口接受了
A
。另一方面,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;
}
模板
结构Foo;
模板
结构Foo{
使用arg_t=arg;
};
模板
结构A{};
模板
结构B{};
模板
结构C{};
int main(){
typename Foo::arg\u t a;
类型名Foo::arg\u t b;
类型名Foo::arg\u t c;
返回0;
}

它真的很难从编译器错误中理解这个问题,而且我无法用谷歌搜索出一个解决方案,这就是为什么我想分享我的

两个注意事项:此解决方案还允许类模板具有多个非默认参数(如
std::map
),而原始代码不允许,并且不允许类模板具有默认的非类型模板,而原始代码不允许。