The following applies a type transformation F
to a list C
of types E...
:
template <template <typename...> class F, typename P> struct apply_t;
template <
template <typename...> class F,
template <typename...> class C, typename... E
> struct apply_t <F, C <E...> > { typedef C <F <E>...> type; };
template <template <typename...> class F, typename P>
using apply = typename apply_t<F, P>::type;
Now, giving this input:
template <typename T> using map1 = T*;
template <typename T> using map2 = const T;
template <typename T> using map3 = const T*;
I get the following output in gcc 4.8.1, using e.g. std::tuple
:
apply <map1, tuple <int, char> > // -> tuple <int*, char*> (OK)
apply <map2, tuple <int, char> > // -> tuple <int, char>
// (tuple <const int, const char> expected)
apply <map3, tuple <int, char> > // -> tuple <const int*, const char*> (OK)
I can see the output types using a utility template function that calls static_assert()
.
I've tried all sorts of combinations. Everything works except for the map const T
in particular, when given as an input type map to apply
. But still works ok if I embed it in the definition of apply
, i.e. typedef C <const E...> type
.
On the other hand, everything works as expected in clang. I may be missing something, but it really seems like a gcc bug to me.
Any ideas?
Here's a complete but reduced testcase, you might want to add this to the GCC bug report (if you need to write one):
template< typename T > using Map = const T;
template< template<typename> class M, typename T >
struct Apply;
template< template<typename> class M, template<typename...> class C, typename... Ts >
struct Apply< M, C<Ts...> > { typedef C<M<Ts>...> type; };
template< typename T > struct A {};
template<typename> void dummy();
int main()
{
dummy< Apply<Map,A<int>>::type >();
}
will fail to link because of
undefined reference to `void dummy<A<int> >()'
instead of the expected
undefined reference to `void dummy<A<const int> >()'
(I know this doesn't solve the problem, but the GCC folks will likely prefer a reduced testcase without any dependency on std::tuple
or any other header).
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