嵌套模板类型的用户定义推导指南
User defined-deduction guide for nested template-types
Q1 : 命名空间范围是否允许用户定义的推导指南?
在此处的示例中,GCC 和 Clang 不会产生相同的行为:
#include <tuple>
template <typename T>
struct some_type;
template <template <typename...> typename T, typename ... Ts>
struct some_type<T<Ts...>>
{
template <typename U>
class nested
{
U member;
public:
nested(U &&){}
};
// non-namespace scope user-deduction-guide : OK with Clang, fix the deduction issue
template <typename U>
nested(U&&) -> nested<U>;
};
void func()
{
using pack_type = std::tuple<int, char>;
some_type<pack_type>::nested{
[](auto &&){}
};
}
简而言之,我们有一个模板参数类型,嵌套类型本身就是模板参数,模板参数之间没有关系。
template <typename T>
struct some_type;
template <template <typename...> typename T, typename ... Ts>
struct some_type<T<Ts...>>
{
template <typename U>
class nested // <- nested type, where `U` as no relationship with `T<Ts...>`
{
U member;
public:
nested(U &&);
};
};
标准规定:http://eel.is/c++draft/temp.deduct.guide#3
[...] A deduction-guide shall be declared in the same scope as the corresponding class template and, for a member class template, with the same access. [...]
Q2 : 如果 no 到 Q1,创建嵌套类型的用户定义推导指南的语法是什么,当有命名空间类型和嵌套类型模板参数之间没有关系吗?
我希望语法接近于:
template <template <typename...> typename T, typename ... Ts>
template <typename U>
some_type<T<Ts...>>::nested<U>::nested(U&&) -> nested<U>;
然而,nested<U>
是 错误的 ,因为它需要一个推导类型...来推导它。
此外,这被解释为具有尾随 return 类型 void
的函数。
template <template <typename...> typename T, typename ... Ts>
template <typename U>
typename some_type<T<Ts...>>::template nested<U>::nested(U&&) -> nested<U>;
感谢您的宝贵时间。
快速修复
我发现的唯一解决方法是为 Clang 添加 user-defined deduction guide
,
这在可维护性方面次优。
Live example on godbolt,
或查看以下来源。
为什么?
- GCC 不允许在非命名空间上下文中进行推导指南,Clang 允许。
- Clang在这方面需要推导指南,GCC不需要
注意:在发帖时,clang trunk 是 11.0.1,gcc trunk 是 10.2
#include <tuple>
template <typename T>
struct type
{
template <typename U>
struct nested
{
template <typename ... nested_Ts>
nested(U &&, std::tuple<nested_Ts...> &&)
{}
};
#if __clang__
// here, user-defined deduction guide only for Clang
template <typename U, typename ... Ts>
nested(U&&, std::tuple<Ts...>&&) -> nested<U>;
#endif
};
void instanciate_symbols()
{
using type = type<int>;
[[maybe_unused]] auto value = type::nested{'a', std::tuple{42, .42f}};
}
Q1 : 命名空间范围是否允许用户定义的推导指南?
在此处的示例中,GCC 和 Clang 不会产生相同的行为:
#include <tuple>
template <typename T>
struct some_type;
template <template <typename...> typename T, typename ... Ts>
struct some_type<T<Ts...>>
{
template <typename U>
class nested
{
U member;
public:
nested(U &&){}
};
// non-namespace scope user-deduction-guide : OK with Clang, fix the deduction issue
template <typename U>
nested(U&&) -> nested<U>;
};
void func()
{
using pack_type = std::tuple<int, char>;
some_type<pack_type>::nested{
[](auto &&){}
};
}
简而言之,我们有一个模板参数类型,嵌套类型本身就是模板参数,模板参数之间没有关系。
template <typename T>
struct some_type;
template <template <typename...> typename T, typename ... Ts>
struct some_type<T<Ts...>>
{
template <typename U>
class nested // <- nested type, where `U` as no relationship with `T<Ts...>`
{
U member;
public:
nested(U &&);
};
};
标准规定:http://eel.is/c++draft/temp.deduct.guide#3
[...] A deduction-guide shall be declared in the same scope as the corresponding class template and, for a member class template, with the same access. [...]
Q2 : 如果 no 到 Q1,创建嵌套类型的用户定义推导指南的语法是什么,当有命名空间类型和嵌套类型模板参数之间没有关系吗?
我希望语法接近于:
template <template <typename...> typename T, typename ... Ts>
template <typename U>
some_type<T<Ts...>>::nested<U>::nested(U&&) -> nested<U>;
然而,nested<U>
是 错误的 ,因为它需要一个推导类型...来推导它。
此外,这被解释为具有尾随 return 类型 void
的函数。
template <template <typename...> typename T, typename ... Ts>
template <typename U>
typename some_type<T<Ts...>>::template nested<U>::nested(U&&) -> nested<U>;
感谢您的宝贵时间。
快速修复
我发现的唯一解决方法是为 Clang 添加 user-defined deduction guide
,
这在可维护性方面次优。
Live example on godbolt,
或查看以下来源。
为什么?
- GCC 不允许在非命名空间上下文中进行推导指南,Clang 允许。
- Clang在这方面需要推导指南,GCC不需要
注意:在发帖时,clang trunk 是 11.0.1,gcc trunk 是 10.2
#include <tuple>
template <typename T>
struct type
{
template <typename U>
struct nested
{
template <typename ... nested_Ts>
nested(U &&, std::tuple<nested_Ts...> &&)
{}
};
#if __clang__
// here, user-defined deduction guide only for Clang
template <typename U, typename ... Ts>
nested(U&&, std::tuple<Ts...>&&) -> nested<U>;
#endif
};
void instanciate_symbols()
{
using type = type<int>;
[[maybe_unused]] auto value = type::nested{'a', std::tuple{42, .42f}};
}