Reputation: 8528
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
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
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