paperjam
paperjam

Reputation: 8528

C++ metafunction to retrieve constexpr from templated base classes

I have code that looks something like this:

template <typename Tag, int v>
struct Const
{
    static constexpr int value = v;
};


struct Compound
    :
    Const<struct T1, 111>,
    Const<struct T2, 222>
{
    Compound(); // constructor is not constexpr
};

I would like to know a compile-time construct (e.g. metafunction) that given either struct T1 or struct T2 as argument can extract as constexpr int 111 or 222 respectively from Compound.

I think I want a metafunction that looks something like this but don't know how to write it:

template <class C, typename Tag>
struct GetConst
{
    static constexpr int value = /* some magic */
};

GetConst<Compound, struct T1>::value == 111
GetConst<Compound, struct T2>::value == 222

Any ideas?

Upvotes: 2

Views: 127

Answers (2)

MikeMB
MikeMB

Reputation: 21166

Slightly different syntax ( constexpr function instead of a static member variable), but here you go:

template <typename Tag, int v>
constexpr int getVal(Const<Tag, v>) {
    return v;
}

template <class C, typename Tag>
constexpr int GetConst() {
    return getVal<Tag>((C*)nullptr);
}

constexpr int value = GetConst<Compound,T2>();
int main() {        
    std::cout << value << std::endl;
}

Upvotes: 2

skypjack
skypjack

Reputation: 50568

A possible solution:

#include<utility>
#include<type_traits>

template <typename Tag, int v>
struct Const { static constexpr int value = v; };

struct T1 {};
struct T2 {};

struct Compound: Const<T1, 111>, Const<T2, 222> { };

template <typename Tag, int N>
constexpr auto f(Const<Tag, N>) {
    return std::integral_constant<int, N>{};
};

int main() {
    static_assert((111 == decltype(f<T1>(std::declval<Compound>()))::value), "!");
    static_assert((222 == decltype(f<T2>(std::declval<Compound>()))::value), "!");
}

You can add one more function to capture the constant and return it if needed.

Upvotes: 2

Related Questions