Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lazy-evaluate dependent-types (CRTP) [duplicate]

Tags:

c++

c++17

crtp

I'd like the following piece of code to work:

template <typename Self>
struct foo_base {
    auto get(typename Self::type n) { return n; }
};

template <typename T>
struct foo : public foo_base<foo<T>> {
    using type = T;
};

The problem of course is that the base is instantiated first so you cannot refer to the derived member types. I'd need some kind of lazy-evaluation here.

I've tried to make the function template and have SFINAE on it, something like:

template <typename Self>
struct foo_base {
    template <typename T, typename = std::enable_if_t<std::is_same_v<T, typename Self::type>>>
    auto get(T n) { return n; }
};

but it doesn't seem to affect the order. Any ideas?

Edit:

Constraints of solution:

  • I can't pass the type as a template parameter from the derived class. Main reason is: The type is very complicated to construct, several hundred characters. So can't do something like struct foo : foo_base<foo<T>, T> or variants.
  • I need to constraint the function to that type, I can't check inside the function. Maybe there are overloads in the derived class.
like image 801
Peter Lenkefi Avatar asked Feb 18 '19 13:02

Peter Lenkefi


1 Answers

You might create external traits, something like:

template <template T>
struct TypeT;

template <typename Self>
struct foo_base {
    auto get(typename TypeT<Self>::type n) { return n; }
};

template <typename T> struct foo;

template <template T>
struct TypeT<foo<T>> {
    using type = T; // Don't use foo<T>::type, so traits can be used with incomplete type
};

template <typename T>
struct foo : public foo_base<foo<T>> {
    using type = typename TypeT<foo>::type; // Or directly = T
};

Else you might indeed use SFINAE, but you must wait the type to be complete (when instantiating the method works in your case), as for example:

template <typename Self>
struct foo_base
{
    template <typename T = Self>
    auto get(typename T::type n) { return n; }
};
like image 55
Jarod42 Avatar answered Sep 21 '22 22:09

Jarod42