class 模板,在定义中引用自己的类型
class template, referring to its own type in definition
我想知道 visual studio 2017 和 GCC 中关于标准的以下情况哪个是正确的。问题是在 class 模板第二个中,visual studio 中的标识符 'second' 总是引用具体类型,但在 gcc 中它似乎是上下文相关的。
GCC 示例
template <typename...>
struct type_list{};
template<template <typename...> typename tmpl>
struct tmpl_c
{
template <typename...Ts> using type = tmpl<Ts...>;
};
template<typename> struct template_of;
template <template <typename...> typename tmpl, typename... Ts>
struct template_of<tmpl<Ts...>>{
using type = tmpl_c<tmpl>;
};
template <typename T>
struct first{};
template <typename T>
struct second
{
// 'second' here refers to second<int>
using test = second;
// 'second' here refers to the template second
// is this due to the context? ie that the tmpl_c is expecting a template not a concrete type?
using types = type_list<tmpl_c<first>, tmpl_c<second> >;
// second here refers to the concrete type 'second<int>'
// this workaround is needed for visual studio as it seems second always
// refers to the concrete type, not the template.
using types2 = type_list<tmpl_c<first>, typename template_of<second>::type >;
};
和 Visual Studio 示例(只有不同的位)
template <typename T>
struct second
{
// 'second' here refers to second<int>
using test = second;
// 'second' here refers to second<int>
// this doesn't compile in visual studio as second<int> not the template.
//using types = type_list<tmpl_c<first>, tmpl_c<second> >;
// second here refers to the concrete type 'second<int>'
// this workaround is needed for visual studio as it seems second always
// refers to the concrete type, not the template.
using types2 = type_list<tmpl_c<first>, typename template_of<second>::type >;
};
由于 template_of
解决方法似乎在两者中都能正常运行,它目前是我唯一的选择..但我仍然想知道哪个是正确的,或者是否有其他解决方法..
Gcc 是正确的。根据injected-class-name for class template的使用规则,injected-class-name也可以用作template-name或type-name。
(强调我的)
Like other classes, class templates have an injected-class-name. The injected-class-name can be used as a template-name or a type-name.
In the following cases, the injected-class-name is treated as a template-name of the class template itself:
- it is followed by <
- it is used as a template argument that corresponds to a template template parameter
- it is the final identifier in the elaborated class specifier of a friend class template declaration.
Otherwise, it is treated as a type-name, and is equivalent to the template-name followed by the template-parameters of the class template enclosed in <>.
也就是说,
template <typename T>
struct second
{
// second is same as second<T>
using test = second;
// second is considered as a template-name
// it's used as template argument for a template template parameter
using types = type_list<tmpl_c<first>, tmpl_c<second> >;
// second is same as second<T>
using types2 = type_list<tmpl_c<first>, typename template_of<second>::type >;
};
我想知道 visual studio 2017 和 GCC 中关于标准的以下情况哪个是正确的。问题是在 class 模板第二个中,visual studio 中的标识符 'second' 总是引用具体类型,但在 gcc 中它似乎是上下文相关的。
GCC 示例
template <typename...>
struct type_list{};
template<template <typename...> typename tmpl>
struct tmpl_c
{
template <typename...Ts> using type = tmpl<Ts...>;
};
template<typename> struct template_of;
template <template <typename...> typename tmpl, typename... Ts>
struct template_of<tmpl<Ts...>>{
using type = tmpl_c<tmpl>;
};
template <typename T>
struct first{};
template <typename T>
struct second
{
// 'second' here refers to second<int>
using test = second;
// 'second' here refers to the template second
// is this due to the context? ie that the tmpl_c is expecting a template not a concrete type?
using types = type_list<tmpl_c<first>, tmpl_c<second> >;
// second here refers to the concrete type 'second<int>'
// this workaround is needed for visual studio as it seems second always
// refers to the concrete type, not the template.
using types2 = type_list<tmpl_c<first>, typename template_of<second>::type >;
};
和 Visual Studio 示例(只有不同的位)
template <typename T>
struct second
{
// 'second' here refers to second<int>
using test = second;
// 'second' here refers to second<int>
// this doesn't compile in visual studio as second<int> not the template.
//using types = type_list<tmpl_c<first>, tmpl_c<second> >;
// second here refers to the concrete type 'second<int>'
// this workaround is needed for visual studio as it seems second always
// refers to the concrete type, not the template.
using types2 = type_list<tmpl_c<first>, typename template_of<second>::type >;
};
由于 template_of
解决方法似乎在两者中都能正常运行,它目前是我唯一的选择..但我仍然想知道哪个是正确的,或者是否有其他解决方法..
Gcc 是正确的。根据injected-class-name for class template的使用规则,injected-class-name也可以用作template-name或type-name。
(强调我的)
Like other classes, class templates have an injected-class-name. The injected-class-name can be used as a template-name or a type-name.
In the following cases, the injected-class-name is treated as a template-name of the class template itself:
- it is followed by <
- it is used as a template argument that corresponds to a template template parameter
- it is the final identifier in the elaborated class specifier of a friend class template declaration.
Otherwise, it is treated as a type-name, and is equivalent to the template-name followed by the template-parameters of the class template enclosed in <>.
也就是说,
template <typename T>
struct second
{
// second is same as second<T>
using test = second;
// second is considered as a template-name
// it's used as template argument for a template template parameter
using types = type_list<tmpl_c<first>, tmpl_c<second> >;
// second is same as second<T>
using types2 = type_list<tmpl_c<first>, typename template_of<second>::type >;
};