Order of preference for SFINAE template? - c++

I'm trying to implement templated structs that take a version parameter.
Here's a simplified example:
template<int Version, class Enable = void>
struct Foo
{
};
template<int Version, class Enable = void>
struct Bar
{
};
/* Base Version of Foo */
template<int Version>
struct Foo<Version, typename enable_if<(Version > 0)>::type>
{
int i;
};
/* Base Version of Bar */
template<int Version>
struct Bar<Version, typename enable_if<(Version > 0)>::type>
{
Foo<Version> foo;
float f;
};
/* Version 2 of Bar */
template<int Version>
struct Bar<Version, typename enable_if<(Version >= 2)>::type>
{
Foo<Version> foo;
float f;
int extraParam;
};
With this approach, there is ambiguity when I use "Bar<2>", because 2 satisfies both the base version's condition (Version > 0) and the version 2 condition (Version >= 2).
I could change the base to require "Version > 0 && Version < 2", but I was hoping to avoid having to do that everywhere. Is there a better way to tell the compiler "Use the highest matching version" for a given template ?

Using the example link provided by dyp, I was able to solve the problem with recursion.
#include <iostream>
#include <type_traits>
using namespace std;
template<int Version>
struct Foo
{
constexpr static bool is_valid = false;
};
template<int Version>
struct Bar
{
constexpr static bool is_valid = false;
};
struct ValidVersion { constexpr static bool is_valid = true; };
/* Base Version of Foo */
template<>
struct Foo<0> : ValidVersion
{
int i;
};
/* Base Version of Bar */
template<>
struct Bar<0> : ValidVersion
{
Foo<0> foo;
float f;
};
/* Version 2 of Bar */
template<>
struct Bar<2> : ValidVersion
{
Foo<2> foo;
float f;
int extraParam;
int extraParam2;
};
template<template<int V> class _Tp, int Version>
struct VersionSelectorImpl
{
template<class T>
struct wrap { using type = T; };
using type = typename std::conditional<_Tp<Version>::is_valid, wrap<_Tp<Version>>, VersionSelectorImpl<_Tp, Version-1>>::type::type;
};
template<template<int V> class _Tp, int Version>
using VersionSelector = typename VersionSelectorImpl<_Tp, Version>::type;
int main() {
cout << "sizeof(<Bar, 1>): " << sizeof(VersionSelector<Bar, 1>) << '\n';
cout << "sizeof(<Bar, 2>): " << sizeof(VersionSelector<Bar, 2>) << '\n';
}
Output:
sizeof(<Bar, 1>): 12
sizeof(<Bar, 2>): 16

Related

C++ Template instancing with mutual reference

Is there a way to allow two or more templates instanciations to mutually refer to each other ?
Example :
/* invalid C++ */
/* we suppose MyTemplate1 and MyTemplate2 are declared */
typedef MyTemplate1<MyInstance2> MyInstance1;
typedef MyTemplate2<MyInstance1> MyInstance2;
I suppose there is none, still asking just in case I missed something.
Adding more precision, I want to achieve such a construction :
/* invalid C++ */
#include <iostream>
template <typename typeT> struct MyStruct1 {
static void print(unsigned i) {
std::cout << "MyStruct1 : " << i << std::endl;
if (i > 0) {
typeT::print(i - 1);
}
}
};
template <typename typeT> struct MyStruct2 {
static void print(unsigned i) {
std::cout << "MyStruct2 : " << i << std::endl;
if (i > 0) {
typeT::print(i - 1);
}
}
};
/* of course this is invalid, since you can't reference MyInstance2
before it is declared */
typedef MyStruct1<MyInstance2> MyInstance1;
typedef MyStruct2<MyInstance1> MyInstance2;
int main() {
MyInstance1::print(5);
return 0;
}
output should be :
MyStruct1 : 5
MyStruct2 : 4
MyStruct1 : 3
MyStruct2 : 2
MyStruct1 : 1
MyStruct2 : 0
Please note I'm not trying to achieve a similar output, but a similar construct, where two (or more) templates instances refer to each other
with as few as possible additional code : it shall be easy to do mutual reference instantiation. However, for the implementation code of the two templates, I don't care if they are complicated.
Here's a solution that at least gives the correct output. If it's also a viable solution for your use case is not very clear though but maybe it can at least help you clarify your question a bit more.
#include <iostream>
template <template <typename> typename TemplateT> struct TemplateType {
template <typename typeT>
static void print(unsigned i) {
TemplateT<typeT>::print(i);
}
};
template <typename typeT> struct MyStruct1 {
static void print(unsigned i) {
std::cout << "MyStruct1 : " << i << std::endl;
if (i > 0) {
typeT::template print<TemplateType<MyStruct1>>(i - 1);
}
}
};
template <typename typeT> struct MyStruct2 {
static void print(unsigned i) {
std::cout << "MyStruct2 : " << i << std::endl;
if (i > 0) {
typeT::template print<TemplateType<MyStruct2>>(i - 1);
}
}
};
typedef MyStruct1<TemplateType<MyStruct2>> MyInstance1;
int main() {
MyInstance1::print(5);
return 0;
}
One way is to use class forward declaration:
template<typename T> class M
{
static int foo(int i) { return i ? T::foo(i - 1) : 0; }
};
struct A;
struct B;
struct A : M<B>{};
struct B : M<A>{};
Not same code exactly but you have recursion.
I finally found a satisfying construct, which involves using a tierce struct acting as a context to declare subs elements. It isn't forcibly the best solution for anyone, and I will probably have to adapt it a bit more to fit my very need, but here is the code :
#include <iostream>
#include <type_traits>
template <typename K, typename T> struct TypePair {
typedef K key;
typedef T type;
};
template <typename Context, typename P0, typename... PN> struct TypeMap {
template <typename K> struct get {
typedef typename std::conditional<
std::is_same<typename P0::key, K>::value,
typename P0::type::template actual<Context>,
typename TypeMap<Context, PN...>::template get<K>::type>::type type;
};
};
struct TypeNotFound {};
template <typename Context, typename P> struct TypeMap<Context, P> {
template <typename K> struct get {
typedef
typename std::conditional<std::is_same<typename P::key, K>::value,
typename P::type::template actual<Context>,
TypeNotFound>::type type;
};
};
/* defining a context to link all classes together */
template <typename... TN> struct Context {
template <typename K> struct Access {
typedef typename TypeMap<Context<TN...>, TN...>::template get<K>::type type;
};
};
/* templates we want to cross ref, note that context is passed as a parameter*/
template <typename ContextT, typename Id2> struct MyStruct1Actual {
static void print(unsigned i) {
std::cout << "MyStruct1 : " << i << std::endl;
if (i > 0) {
ContextT::template Access<Id2>::type::print(i - 1);
}
}
};
template <typename ContextT, typename Id1> struct MyStruct2Actual {
static void print(unsigned i) {
std::cout << "MyStruct2 : " << i << std::endl;
if (i > 0) {
ContextT::template Access<Id1>::type::print(i - 1);
}
}
};
/* wrappers to not have to always pass context when instancing templates */
template <typename type> struct MyStruct1 {
template <typename ContextT> using actual = MyStruct1Actual<ContextT, type>;
};
template <typename type> struct MyStruct2 {
template <typename ContextT> using actual = MyStruct2Actual<ContextT, type>;
};
/* Enum and dummy id, could simply use Enum actually, but using classes a Id
can prove to be more elegant with complex structures, expecially as it could be
used to automatically create pairs instead of having to precise Id */
enum Ids : int { Struct1, Struct2 };
template <Ids id> struct Id {};
// instancing all stuff withing context
// clang-format off
typedef Context<
TypePair< Id<Struct1>, MyStruct1< Id<Struct2> > >,
TypePair< Id<Struct2>, MyStruct2< Id<Struct1> > >
> Ctx;
// clang-format on
typedef Ctx::Access<Id<Struct1>>::type S1;
int main() {
S1::print(5);
return 0;
}
Shortening names an giving more meaning than Context or TypePair will be mandatory, but the idea is here.

multiple virtual inheritance and variadic template

In my project I played with the following design :
enum {
A = 1, B = 2, C = 4
};
struct Foo { int foo; };
template <int> struct Bar;
template <> struct Bar<A> : public virtual Foo { int a; };
template <> struct Bar<B> : public virtual Foo { int b; };
template <> struct Bar<C> : public virtual Foo { int c; };
Now I can do something fun like :
template <> struct Bar<A|B> : public A, public B {};
template <> struct Bar<A|C> : public A, public C {};
template <> struct Bar<B|C> : public B, public C {};
template <> struct Bar<A|B|C> : public A, public B, public C {};
So that I can write :
Bar<A|C> bar;
bar.foo = 2;
bar.a = 1;
bar.c = 2;
Now I would like the generation of the combination classes Bar<X|Y|Z|..> to be automatically done when the user creates such an instance.
Is this possible using some template magic ?
Something along the lines of :
template <int N, class ...Classes> struct Bar<N> : public Classes... {};
template <int N> struct Bar<N> : public Bar<N, generate_classes<N> > {};
where generate_classes would be able to generate the list of classes Bar<N> should inherit from.
No need in fancy schmancy SFINAE, parameter packs or any such dark wizardry.
enum {
A = 1, B = 2, C = 4
};
struct Foo { int foo; };
template <unsigned int> struct Bar; // unsigned because bit fiddling
template <> struct Bar<A> : public virtual Foo { int a; };
template <> struct Bar<B> : public virtual Foo { int b; };
template <> struct Bar<C> : public virtual Foo { int c; };
template <unsigned int i> struct Bar :
public Bar<i & ~(i-1)>, // only least significant set bit
public Bar<i & (i-1)> // all other set bits
{ };
// checking
int main ()
{
Bar<A|B|C> abc;
abc.a = 0; // ok
abc.b = 0; // ok
abc.c = 0; // ok
Bar<A|B> ab;
ab.a = 0; // ok
ab.b = 0; // ok
ab.c = 0; // error
Bar<A|C> ac;
ac.a = 0; // ok
ac.b = 0; // error
ac.c = 0; // ok
Bar<9> x; // error
}
Instead of thinking about somehow generating a list of classes to be inherited you can think of it as choosing them. This one should be inherited, this one shouldn't. This can be achieved by static dispatching through template parameter. So we get a template that based on a bool parameter gives either T or an empty class. It is likely to be optimized (it may even be guaranteed in this case, but I'm not sure what exact requirements given by the standard are) by empty base optimization so there is no memory overhead.
#include <iostream>
enum {
A = 1, B = 2, C = 4
};
template <class T, bool Enable>
struct or_empty;
template <class T>
struct or_empty<T, false>
{
struct empty {};
using type = empty;
};
template <class T>
struct or_empty<T, true>
{
using type = T;
};
template <class T, bool Enable>
using or_empty_t = typename or_empty<T, Enable>::type;
struct Foo { int foo; };
template <int I> struct Bar :
public or_empty_t<Bar<A>, I&A>,
public or_empty_t<Bar<B>, I&B>,
public or_empty_t<Bar<C>, I&C> {};
template <> struct Bar<A> : public virtual Foo { int a; };
template <> struct Bar<B> : public virtual Foo { int b; };
template <> struct Bar<C> : public virtual Foo { int c; };
int main()
{
Bar<A|C> bar;
bar.foo = 2;
bar.a = 1;
// bar.b = 2; error
bar.c = 2;
std::cout << bar.foo << ' ' << bar.a << ' ' << bar.c << '\n';
std::cout << sizeof(Bar<A>) << ' ' << sizeof(Bar<A|B>) << ' ' << sizeof(Bar<A|B|C>) << '\n';
}
Demo: http://coliru.stacked-crooked.com/a/f170fbd873739c38
Some machinery to do compile-time unpacking of flags:
enum flag_e { None = 0, A = 1, B = 1<<1, C = 1<<2 };
template<flag_e...>
struct flags {using type=flags; constexpr flags(){}};
template<flag_e>
struct flag{using type=flag; constexpr flag(){}};
constexpr flags<A,B,C> all_flags{};
template<flag_e...lhs, flag_e...rhs>
constexpr flags<lhs...,rhs...> operator+(flags<lhs...>, flags<rhs...>)
{ return {}; }
template<flag_e lhs, flag_e...rhs>
inline constexpr flags<lhs, rhs...> operator+(flag<lhs>, flags<rhs...>)
{ return {}; }
template<flag_e...lhs, flag_e rhs>
inline constexpr flags<lhs..., rhs> operator+(flags<lhs...>, flag<rhs>)
{ return {}; }
template<flag_e...fs>
inline constexpr flags<fs...> operator+(flag<None>, flags<fs...>)
{ return {}; }
template<flag_e...fs>
inline constexpr flags<fs...> operator+(flags<fs...>, flag<None>)
{ return {}; }
template<flag_e f, flag_e...fs>
inline constexpr auto unpack( flag<f>, flags<fs...> x, flags<> )
-> flags<fs...>
{ return {}; }
template<flag_e f, flag_e...fs, flag_e c0, flag_e...checks>
inline constexpr auto unpack( flag<f> fin, flags<fs...> x, flags<c0, checks...> )
-> decltype( unpack( fin, x+flag<flag_e(f&c0)>{}, flags<checks...>{} ) )
{ return {}; }
template<flag_e f>
inline constexpr auto unpack( flag<f> fin )
-> decltype( unpack( flag<f>{}, flags<>{}, all_flags ) )
{ return {}; }
Then we use it:
template <int> struct Bar;
template <class flags> struct BarImpl;
template <flag_e...fs> struct BarImpl<flags<fs...>>:
Bar<fs>...
{};
template <int flags> struct Bar:
BarImpl<decltype(unpack(flag<flag_e(flags)>{}))>
{};
struct Foo { int foo; };
template <> struct Bar<A> : public virtual Foo { int a; };
template <> struct Bar<B> : public virtual Foo { int b; };
template <> struct Bar<C> : public virtual Foo { int c; };
Live example.
The code that lets you have bundles of flags and individual flags can be made more generic at the cost of mentioning the flag_e type more often.
I made it overly slick, with the ability to say flags<A>+flags<B> and get flags<A,B>, because I like that notation.
I then wrote unpack, which takes flag<A|B> and produces flags<A,B>.
In C++14 and 17 things get slicker, which folds and return type deduction and the like.

How to detect whether there is actually a specific member variable in class?

I am purposely using the very same title as this question because I feel that the answer that was accepted does not account for a problem that I am stuck into.
I am looking for a way to detect if some class has some member variable. It is fundamental to note that I am looking for a variable, not a member function or anything else.
Here is the example provided in the question I linked:
template<typename T> struct HasX {
struct Fallback { int x; }; // introduce member name "x"
struct Derived : T, Fallback { };
template<typename C, C> struct ChT;
template<typename C> static char (&f(ChT<int Fallback::*, &C::x>*))[1];
template<typename C> static char (&f(...))[2];
static bool const value = sizeof(f<Derived>(0)) == 2;
};
struct A { int x; };
struct B { int X; };
int main() {
std::cout << HasX<A>::value << std::endl; // 1
std::cout << HasX<B>::value << std::endl; // 0
}
But we will get the very same output if we do something like
template<typename T> struct HasX {
struct Fallback { int x; }; // introduce member name "x"
struct Derived : T, Fallback { };
template<typename C, C> struct ChT;
template<typename C> static char (&f(ChT<int Fallback::*, &C::x>*))[1];
template<typename C> static char (&f(...))[2];
static bool const value = sizeof(f<Derived>(0)) == 2;
};
struct A {
void x()
{
}
};
struct B { int X; };
int main() {
std::cout << HasX<A>::value << std::endl; // 1
std::cout << HasX<B>::value << std::endl; // 0
}
(Please note that in the second example the int x in A was substituted with a member function void x()).
I have no real idea on how to work around this problem. I partially fixed this by doing something like
template <bool, typename> class my_helper_class;
template <typename ctype> class my_helper_class <true, ctype>
{
static bool const value = std :: is_member_object_pointer <decltype(&ctype :: x)> :: value;
};
template <typename ctype> class my_helper_class <false, ctype>
{
static bool const value = false;
};
template <typename T> struct HasX
{
// ...
static bool const value = my_helper_class <sizeof(f <Derived>(0)) == 2, T> :: value;
};
Which actually selects if I am using an object. However, the above doesn't work if there are more overloaded functions with the same name x in my class.
For example if I do
struct A
{
void x()
{
}
void x(int)
{
}
};
Then the pointer is not resolved successfully and the a call to HasX <A> doesn't compile.
What am I supposed to do? Is there any workaround or simpler way to get this done?
The problem is that HasX only checks if the name x exists. The ... gets selected if &C::x is ambiguous (which happens if it matches both in Fallback and T). The ChT<> overload gets selected only if &C::x is exactly Fallback::x. At no point are we actually checking the type of T::x - so we never actually check if x is a variable or function or whatever.
The solution is: use C++11 and just check that &T::x is a member object pointer:
template <class T, class = void>
struct HasX
: std::false_type
{ };
template <class T>
struct HasX<T,
std::enable_if_t<
std::is_member_object_pointer<decltype(&T::x)>::value>
>
: std::true_type { };
If &T::x doesn't exist, substitution failure and we fallback to the primary template and get false_type. If &T::x exists but is an overloaded name, substitution failure. If &T::x exists but is a non-overloaded function, substitution failure on enable_if_t<false>. SFINAE for the win.
That works for all of these types:
struct A {
void x()
{
}
void x(int)
{
}
};
struct B { int X; };
struct C { int x; };
struct D { char x; };
int main() {
static_assert(!HasX<A>::value, "!");
static_assert(!HasX<B>::value, "!");
static_assert(HasX<C>::value, "!");
static_assert(HasX<D>::value, "!");
}

Simplifying template parameters

Take the following struct:
template<typename T,T value>
struct A{
};
I would like to use it like this:
A<12> a; //A<12> should become A<int,12>
But this is not allowed. Why is it not allowed? (and is there a workaround?)
Not sure what you want, but perhaps this?
#include <iostream>
template <typename T, T value>
struct A {
void foo() const { std::cout << "A<int, " << value << ">::foo called\n"; }
};
// Sample partial specialization that you might want.
template <std::size_t value>
struct A<std::size_t, value> {
void foo() const { std::cout << "A<std::size_t, " << value << ">::foo called\n"; }
};
template <int N>
using B = A<int, N>;
template <int N, typename T = int>
using C = A<T, static_cast<T>(N)>;
int main() {
B<12> a;
a.foo(); // A<int, 12>::foo called
C<12> c;
c.foo(); // A<int, 12>::foo called
C<12, std::size_t> d;
d.foo(); // A<std::size_t, 12>::foo called
}
Maybe the closest you're going to get is to use a meta-factory:
template<class T, T value>
struct A
{};
template<class T = int>
struct factory
{
template<T V> using A = ::A<T, V>;
};
int main()
{
auto x = factory<>::A<12> {};
auto y = factory<short>::A<45> {};
}

How to build Type2Int from Int2Type?

I have Int2Type specialization
struct A;
struct B;
template<int i> Int2Type;
template<> Int2Type<1> { typedef A type; };
template<> Int2Type<2> { typedef B type; };
Can I build reverse Type2Int specialization automatically? Type2Int<A>::value==1 and so on
Thank you
PS Of course, I can define macro
#define I2T(i, T) template<> Int2Type<i> { typedef T type; }; template<> Type2Int<T> { static const int value = i; };
but I don't want change existing code, may be exists some other way...
update
A, B and others lives in different files
common.h
template<int i> Int2Type;
a.h
struct A;
template<> Int2Type<1> { typedef A type; };
b.h
struct B;
template<> Int2Type<2> { typedef B type; };
I need two compile-time "maps" - type by int and int by type;
Int2Type<1>::type a;
someFunc(Type2Int<A>::value)
Directly? No. Such a thing would be impossible in C++. But, with an intermediate type, we could implement such a thing ourselves with a few helpers.
Without C++11, check out the Boost.MPL library. Specifically, we want boost::mpl::vector:
typedef boost::mpl::vector<A, B> IndexedTypes;
template <int I>
struct Int2Type {
typedef typename boost::mpl::at<IndexedTypes,
boost::mpl::int_<I - 1>
>::type type;
};
template <typename T>
struct Type2Int {
typedef typename boost::mpl::begin<IndexedTypes>::type begin;
typedef typename boost::mpl::find<IndexedTypes, T>::type iter;
static const int value = boost::mpl::distance<begin, iter>::type::value + 1;
};
That should give you Int2Type<1>::type as A, and Type2Int<B> as 2.
With C++11, we can write these as short metafunctions based on a variadic sequence:
template <typename...> struct sequence { };
using IndexedTypes = sequence<A, B>;
can you re-arrange your code to be more like this?
struct A;
struct B;
template<int I, class Type>
struct Int2Type
{
static const int value = I;
typedef Type type;
};
using type1 = Int2Type<1, A>;
using type2 = Int2Type<2, B>;
This works for me:
#include <iostream>
int getNextInt()
{
static int next = 0;
return ++next;
}
template <typename T> struct TypeToInt
{
static const int value;
};
template <typename T> const int TypeToInt<T>::value = getNextInt();
struct A;
struct B;
struct C;
int main()
{
std::cout << TypeToInt<A>::value << std::endl;
std::cout << TypeToInt<B>::value << std::endl;
std::cout << TypeToInt<C>::value << std::endl;
}
Output:
1
2
3