In the example here, GCC and Clang does not produce the same behavior :
#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 &&){}
};
}
In short, we have a template-parametered type, with a nested type which is itself template-parametered, and template parameters have no relationship between each others.
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 &&);
};
};
The standard specify : 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. [...]
I'd expect a syntax close to :
template <template <typename...> typename T, typename ... Ts>
template <typename U>
some_type<T<Ts...>>::nested<U>::nested(U&&) -> nested<U>;
However, nested<U>
is wrong, as it required a deduced type ... to deduce it.
Also, this is interpreted as a function with trailing return type void
.
template <template <typename...> typename T, typename ... Ts>
template <typename U>
typename some_type<T<Ts...>>::template nested<U>::nested(U&&) -> nested<U>;
Thanks for your time.
The only work-around I found is to add a user-defined deduction guide
only for Clang,
which is way sub-optimal in term of maintainability.
Live example on godbolt,
or see the sources below.
NB : As posting this, clang trunk is 11.0.1 and gcc trunk is 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}};
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With