英文:
Nested templated type compiles in VisualStudio but not on GCC
问题
以下是代码的中文翻译:
我有以下的模式:
template<class T, int Cap>
struct stack_collection
{
};
template<int Cap>
struct generate_stack_collection
{
template<class T>
using type = stack_collection<T, Cap>
};
template<template<class> class Col>
class collection_user
{
};
int main()
{
collection_user<typename generate_stack_collection<5>::type> col;
}
这段代码在Visual Studio/MSVC上可以编译通过,但在GCC上不行,参见:https://godbolt.org/z/W8hdM87cd
我感觉我可能漏掉了一些 "template" 和/或 "typename" 指令,但是我似乎无法让GCC满意。
我需要添加什么才能使这在GCC中编译通过?
这是GCC的错误信息:
```cpp
<source>: 在函数 'int main()' 中:
<source>:23:64: 错误:在没有参数列表的情况下无效使用模板名 'generate_stack_collection<5>::type'
23 | collection_user<typename generate_stack_collection<5>::type> col;
| ^~~~
<source>:12:15: 注意:在此处声明了 'template<class T> using type = stack_collection<T, 5>'
12 | using type = stack_collection<T, Cap>
| ^~~~
<source>:23:68: 错误:模板参数 1 无效
23 | collection_user<typename generate_stack_collection<5>::type> col;
| ^
汇编生成编译器返回:1
<source>: 在函数 'int main()' 中:
<source>:23:64: 错误:在没有参数列表的情况下无效使用模板名 'generate_stack_collection<5>::type'
23 | collection_user<typename generate_stack_collection<5>::type> col;
| ^~~~
<source>:12:15: 注意:在此处声明了 'template<class T> using type = stack_collection<T, 5>'
12 | using type = stack_collection<T, Cap>
| ^~~~
<source>:23:68: 错误:模板参数 1 无效
23 | collection_user<typename generate_stack_collection<5>::type> col;
| ^
执行生成编译器返回:1
英文:
I have the following pattern:
template<class T, int Cap>
struct stack_collection
{
};
template<int Cap>
struct generate_stack_collection
{
template<class T>
using type = stack_collection<T, Cap>;
};
template<template<class> class Col>
class collection_user
{
};
int main()
{
collection_user<typename generate_stack_collection<5>::type> col;
}
This compiles fine on visual studio/MSVC, but not on GCC, see: https://godbolt.org/z/W8hdM87cd
I have a feeling I am missing some "template" and/or "typename" directives, but I cannot seem to get GCC to be happy.
what am I missing for this to compile in GCC?
Here is what gcc says:
<source>: In function 'int main()':
<source>:23:64: error: invalid use of template-name 'generate_stack_collection<5>::type' without an argument list
23 | collection_user<typename generate_stack_collection<5>::type> col;
| ^~~~
<source>:12:15: note: 'template<class T> using type = stack_collection<T, 5>' declared here
12 | using type = stack_collection<T, Cap>;
| ^~~~
<source>:23:68: error: template argument 1 is invalid
23 | collection_user<typename generate_stack_collection<5>::type> col;
| ^
ASM generation compiler returned: 1
<source>: In function 'int main()':
<source>:23:64: error: invalid use of template-name 'generate_stack_collection<5>::type' without an argument list
23 | collection_user<typename generate_stack_collection<5>::type> col;
| ^~~~
<source>:12:15: note: 'template<class T> using type = stack_collection<T, 5>' declared here
12 | using type = stack_collection<T, Cap>;
| ^~~~
<source>:23:68: error: template argument 1 is invalid
23 | collection_user<typename generate_stack_collection<5>::type> col;
| ^
Execution build compiler returned: 1
答案1
得分: 3
The typename
keyword is wrong here, since the type
member is not actually a type, but a template. Therefore just get rid of the typename
and it'll work for both compilers (msvc is technically wrong in accepting the typename variant, but eh...):
collection_user<generate_stack_collection<5>::type> col;
However, in this case you are in the situation where you are explicitly instantiating the generate_stack_collection
template you have there; if you want to use a dependent template parameter, you have to use the template
keyword - but in contrast to typename
you add that after the ::
:
template<int X>
using C = collection_user<generate_stack_collection<X>::template type>;
int main()
{
C<5> col;
return 0;
}
This code should work in any compliant compiler (and will work in gcc/msvc on godbolt if you try it).
英文:
The typename
keyword is wrong here, since the type
member is not actually a type, but a template. Therefore just get rid of the typename
and it'll work for both compilers (msvc is technically wrong in accepting the typename variant, but eh...):
collection_user<generate_stack_collection<5>::type> col;
However, in this case you are in the situation where you are explicitly instantiating the generate_stack_collection
template you have there; if you want to use a dependent template parameter, you have to use the template
keyword - but in contrast to typename
you add that after the ::
:
template<int X>
using C = collection_user<generate_stack_collection<X>::template type>;
int main()
{
C<5> col;
return 0;
}
This code should work in any compliant compiler (and will work in gcc/msvc on godbolt if you try it).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论