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.

2 Answers2

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

Evg
  • 25,259
  • 5
  • 41
  • 83
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{};
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • 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>::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 >::value` really is `true` (https://godbolt.org/z/nNvtKz) – 463035818_is_not_an_ai Apr 17 '20 at 19:45
  • @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. – HTNW Apr 17 '20 at 19:57
  • @HTNW 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... – 463035818_is_not_an_ai Apr 17 '20 at 20:00
  • @HTNW 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 question – 463035818_is_not_an_ai Apr 17 '20 at 20:03
  • @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. – HTNW Apr 17 '20 at 20:07
  • @HTNW given two arbitrary templates I do understand what you say, but here `template_class>::type` is `Foo` without any doubts – 463035818_is_not_an_ai Apr 17 '20 at 20:10
  • @HTNW lets not spam here, I am writing the question and I am looking forward to your answer – 463035818_is_not_an_ai Apr 17 '20 at 20:11
  • 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. – HTNW Apr 17 '20 at 20:13
  • @HTNW thanks. You already made me realize that my initial expectations were not completely reasonable. – 463035818_is_not_an_ai Apr 17 '20 at 20:24
  • But if we use `template_class` on both arguments? Will they be equal then? – hououin kyouma Apr 18 '20 at 09:53