I work with template template parameters and want to construct new types based on template template parameters defined at another location. This sometimes works, but I think I miss something fundamentally, conceptually.
In the below minimal (I hope not too much distorted) example I expect the types of Example<GerericTemplate>
and MakeAnotherX<Example<GenericTemplate>>::type
to be identical, but they aren't always.
struct Something {};
template <template <typename> typename TemplateParameter>
struct Example {
template <typename T>
using InputTemplate = TemplateParameter<T>;
using FullType = TemplateParameter<Something>;
private:
FullType fData;
};
template <typename T>
struct GenericTemplate {};
// this works with (recent) GCC, but the static_assert below fails with clang
template <typename ExistingType,
template <typename> typename _InputTemplate
= ExistingType::template InputTemplate>
struct MakeAnother1 {
using type = Example<_InputTemplate>;
};
// this compiles, but static_assert below fails for both (recent) gcc and clang
template <typename ExistingType>
struct MakeAnother2 {
template <typename T> using _InputTemplate
= typename ExistingTemplate::template InputTemplate<T>;
using type = Example<_InputTemplate>;
};
#include <type_traits>
int main() {
using type1 = Example<GenericTemplate>;
static_assert(std::is_same<type1, MakeAnother1<type1>::type >::value, "this is not the same");
static_assert(std::is_same<type1, MakeAnother2<type1>::type >::value, "this is not the same");
return 0;
}
So far I am using gcc and clang (-std=c++17) for testing (and production), but in general I just wish to have standard compliant code. I really would like to be able to to reuse template template parameters in different context and classes as described in the minimal example above.
What is the correct way to achieve this in a robust manner? Also: is the fact that MakeAnother1 works with GCC a feature or a bug of GCC (and vice versa for clang)?
The "real code" is significantly more complex, so in particular I want those "Make" helper structs to work on new types.
Update
An earlier conceptually identical version of this question was asked about 6 years ago see old post. The news is that today this work on gcc version 5 and beyond but still no other compiler seems to support it. Unfortunately the discussion on CWG seems to have stalled on this point and could benefit from a reminder?
At this stage: after this update, if you prefer we can of course close this report here now. Thanks for all help!