Is there a way to get type of template class from its complete type?
Asked Answered
I

2

2

I need a meta-function that for given complete class type returns its template (e.g. f<foo<bar>>::type or f<foo<baz>>::type results in foo).

Or it may return true on f<foo<bar>, foo<baz>>::value and false on f<foo<bar>, not_foo<baz>>::value

P.S: this was meant to be used with many chrono::duration like classes (but for weight units, mass units and so on). I needed different units not to convert one to another.

Isaacs answered 17/4, 2020 at 18:51 Comment(6)
Or it may return true on f<foo<bar>, foo<baz>>::value and false on f<foo1<bar>, foo2<bar>>::valueIsaacs
Are you looking for decltype?Appendage
Instead of adding comments you can edit your question.Hillhouse
decltype will result in complete type foo<bar> instead of fooIsaacs
the type trait to get true and false can be done, to get foo without mentioning for first I am not sure if it is even possible. Would a is_instantiation_of_foo < foo<bar> > suffice?Falcone
No, because the programm is unaware of type foo (It's base class for many derived which i need too catch)Isaacs
J
3

f<foo<bar>>::type or f<foo<baz>>::type results in foo

Not exactly (see is-an-alias-template-considered-equal-to-the-same-template), you can do something like:

template <typename T> struct template_class;

template <template <typename> class C, typename T>
struct template_class<C<T>>
{
    template <typename U>
    using type = C<U>;
};

Or it may return true on f<foo<bar>, foo<baz>>::value and false on f<foo<bar>, not_foo<baz>>::value

It is easier, even if limited, specialization mostly as is_same:

template <typename, typename> struct has_same_template_class : std::false_type{};

template <template<typename> class C, typename T1, typename T2>
struct has_same_template_class<C<T1>, C<T2>> : std::true_type{};
Joly answered 17/4, 2020 at 19:24 Comment(10)
why "not exactly" ? I was trying to get exactly that without success. Your template_class can be used to get foo from template_class< foo<int>>::type, isnt that what OP asked for? Of course there isnt much one can to with the template, but eg one can write a is_same_template to see that is_same_template< foo, template_class< foo<int> >::value really is true (godbolt.org/z/nNvtKz)Falcone
@idclev463035818 Clang doesn't agree. All things considered, I don't think the standard would require implementations to implement arbitrary equality of functions (given that it is impossible), so the correct result of that is either false, "implementation-defined", or "undefined", none of which are desirable.Mcdaniels
@Mcdaniels sorry I dont fully understand what you say. "arbitrary equality of functions" ? There is no function involved. I will take a look at clang, maybe then I'll understand...Falcone
@Mcdaniels i suppose you meant templates, not functions. Now I get it, the type template alias isn't really the same template as foo, it just "looks like". Now I am curious what exactly is implementation defined about it, maybe I'll open a questionFalcone
@idclev463035818 Templates are a form of mathematical function. Given two arbitrary functions (templates) with infinite domains (infinitely many types that can be inputs), there's simply no way to decide whether they're equal at every point (extensionally equal). Since all our functions can be written out in finitely many symbols (the actual syntax used to write them), you can easily get the stronger intensional equality, where you check that that the "syntax" or "identity" is the same.Mcdaniels
@Mcdaniels given two arbitrary templates I do understand what you say, but here template_class<Foo<T>>::type is Foo without any doubtsFalcone
@Mcdaniels lets not spam here, I am writing the question and I am looking forward to your answerFalcone
Ok, now what happens when it gets more complicated? When it comes to this question (and it's a common issue), it's often better to not even try and give a predictable answer (false, not equal) than to try to do the impossible and be unpredictable. I don't know what the standard says (so I can't answer the question), but I would not rely on equality of templates working, as anyway we have evidence of compiler dependence.Mcdaniels
@Mcdaniels thanks. You already made me realize that my initial expectations were not completely reasonable.Falcone
But if we use template_class on both arguments? Will they be equal then?Isaacs
J
3

Probably, you want something like this:

#include <type_traits>

template<class> struct foo;
template<class> struct not_foo;

struct bar;
struct baz;

template<class, class>
struct trait : std::false_type {};

template<template<class> class T, class S1, class S2>
struct trait<T<S1>, T<S2>> : std::true_type {};

static_assert( trait<foo<bar>,     foo<baz>    >::value);
static_assert( trait<not_foo<bar>, not_foo<baz>>::value);
static_assert(!trait<foo<bar>,     not_foo<baz>>::value);
static_assert(!trait<foo<bar>,     not_foo<bar>>::value);

Demo

Junji answered 17/4, 2020 at 19:20 Comment(3)
This won't work with multiple template params right?Epiboly
@sparik, as written, it won't. But you can write template<template<class...> class T, class... S1, class... S2> struct trait<T<S1...>, T<S2...>>.Junji
This is indeed a solution to the second question! Thanks.Isaacs
J
3

f<foo<bar>>::type or f<foo<baz>>::type results in foo

Not exactly (see is-an-alias-template-considered-equal-to-the-same-template), you can do something like:

template <typename T> struct template_class;

template <template <typename> class C, typename T>
struct template_class<C<T>>
{
    template <typename U>
    using type = C<U>;
};

Or it may return true on f<foo<bar>, foo<baz>>::value and false on f<foo<bar>, not_foo<baz>>::value

It is easier, even if limited, specialization mostly as is_same:

template <typename, typename> struct has_same_template_class : std::false_type{};

template <template<typename> class C, typename T1, typename T2>
struct has_same_template_class<C<T1>, C<T2>> : std::true_type{};
Joly answered 17/4, 2020 at 19:24 Comment(10)
why "not exactly" ? I was trying to get exactly that without success. Your template_class can be used to get foo from template_class< foo<int>>::type, isnt that what OP asked for? Of course there isnt much one can to with the template, but eg one can write a is_same_template to see that is_same_template< foo, template_class< foo<int> >::value really is true (godbolt.org/z/nNvtKz)Falcone
@idclev463035818 Clang doesn't agree. All things considered, I don't think the standard would require implementations to implement arbitrary equality of functions (given that it is impossible), so the correct result of that is either false, "implementation-defined", or "undefined", none of which are desirable.Mcdaniels
@Mcdaniels sorry I dont fully understand what you say. "arbitrary equality of functions" ? There is no function involved. I will take a look at clang, maybe then I'll understand...Falcone
@Mcdaniels i suppose you meant templates, not functions. Now I get it, the type template alias isn't really the same template as foo, it just "looks like". Now I am curious what exactly is implementation defined about it, maybe I'll open a questionFalcone
@idclev463035818 Templates are a form of mathematical function. Given two arbitrary functions (templates) with infinite domains (infinitely many types that can be inputs), there's simply no way to decide whether they're equal at every point (extensionally equal). Since all our functions can be written out in finitely many symbols (the actual syntax used to write them), you can easily get the stronger intensional equality, where you check that that the "syntax" or "identity" is the same.Mcdaniels
@Mcdaniels given two arbitrary templates I do understand what you say, but here template_class<Foo<T>>::type is Foo without any doubtsFalcone
@Mcdaniels lets not spam here, I am writing the question and I am looking forward to your answerFalcone
Ok, now what happens when it gets more complicated? When it comes to this question (and it's a common issue), it's often better to not even try and give a predictable answer (false, not equal) than to try to do the impossible and be unpredictable. I don't know what the standard says (so I can't answer the question), but I would not rely on equality of templates working, as anyway we have evidence of compiler dependence.Mcdaniels
@Mcdaniels thanks. You already made me realize that my initial expectations were not completely reasonable.Falcone
But if we use template_class on both arguments? Will they be equal then?Isaacs

© 2022 - 2024 — McMap. All rights reserved.