Руководство пользователя по выводу для вложенных типов-шаблонов
Q1 : Допускаются ли определяемые пользователем руководства по дедукции в области пространства имен?
В приведенном здесь примере GCC и Clang не ведут себя одинаково:
Короче говоря, у нас есть тип, параметризованный шаблоном, с вложенным типом, который сам параметрируется шаблоном, а параметры шаблона не имеют взаимосвязи друг с другом.
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
[...] Руководство по дедукции должно быть объявлено в той же области, что и соответствующий шаблон класса, и для шаблона класса-члена с тем же доступом. [...]
Q2 : Если нет для Q1, каков синтаксис для создания определяемого пользователем руководства по выводу для вложенного типа, когда нет связи между типом пространства имен и параметрами шаблона вложенного типа?
Я бы ожидал синтаксиса, близкого к:
template <template <typename...> typename T, typename ... Ts>
template <typename U>
some_type<T<Ts...>>::nested<U>::nested(U&&) -> nested<U>;
Тем не мение,
nested<U>
это не так , как это требовалось выведенный тип ... вывести его.
Кроме того, это интерпретируется как функция с конечным возвращаемым типом.
void
.
template <template <typename...> typename T, typename ... Ts>
template <typename U>
typename some_type<T<Ts...>>::template nested<U>::nested(U&&) -> nested<U>;
Спасибо за ваше время.
1 ответ
Быстрая починка
Единственный обходной путь, который я нашел, это добавить
который не оптимален с точки зрения ремонтопригодности.
Живой пример на godbolt или
смотрите исходники ниже.
Почему ?
- GCC не разрешает руководство по дедукции в контексте, отличном от пространства имен, в отличие от Clang .
- В этом контексте для Clang требуется руководство по дедукции, а для GCC — нет .
NB: на момент публикации этот ствол clang — 11.0.1, а ствол gcc — 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}};
}