Meta-iteration over variadic templates arguments - c++

I would like to generalize the following pattern:
template<class A1, class A2, class A3>
class Foo {
protected:
template<class T>
void foo(const T& t) {...do stuff...}
public:
void bar(const A1& a) { foo(a); }
void bar(const A2& a) { foo(a); }
void bar(const A3& a) { foo(a); }
};
The above approach does not scale with a number of increasing arguments. So, I'd like to do:
template<class As...>
class Foo {
protected:
template<class T>
void foo(const t& a) {...do stuff...}
public:
for each type A in As declare:
void bar(const A& a) { foo(a); }
};
Is there a way to do it?

another approach could be to have a check in bar to test if the type is in the sequence, else barf with a useful error message, this avoid any inheritance tricks..
#include <iostream>
struct E {};
struct F {};
template <class... As>
class Foo
{
template <typename U>
static constexpr bool contains() {
return false;
}
template <typename U, typename B, typename ...S>
static constexpr bool contains() {
return (std::is_same<U, B>::value)? true : contains<U, S...>();
}
protected:
template <class T>
void foo(const T& a) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
public:
template <class T>
void bar(const T& a) {
static_assert(contains<T, As...>(), "Type does not exist");
foo(a);
}
};
int main()
{
Foo<E, F, E, F> f;
f.bar(F{});
f.bar(E{});
f.bar(1); // will hit static_assert
}

In case you don't actually need the bars and instead just need to constrain foo - we can use SFINAE to allow a call to it only with a type convertible to one of the As:
template <class... As>
class Foo {
public:
template <class T,
class = std::enable_if_t<any<std::is_convertible<T, As>::value...>::value>>
void foo(T const&) { ... }
};
Where we can implement any with something like the bool_pack trick:
template <bool... b> struct bool_pack { };
template <bool... b>
using any = std::integral_constant<bool,
!std::is_same<bool_pack<b..., false>, bool_pack<false, b...>>::value>;

template <class CRTP, class A, class... As>
struct FooBar
{
void bar(const A& a)
{
static_cast<CRTP*>(this)->foo(a);
}
};
template <class CRTP, class A, class B, class... As>
struct FooBar<CRTP, A, B, As...> : FooBar<CRTP, B, As...>
{
using FooBar<CRTP, B, As...>::bar;
void bar(const A& a)
{
static_cast<CRTP*>(this)->foo(a);
}
};
template <class... As>
class Foo : FooBar<Foo<As...>, As...>
{
template <class, class, class...>
friend struct FooBar;
protected:
template <class T>
void foo(const T& a) { }
public:
using FooBar<Foo, As...>::bar;
};
DEMO

template <class A, class... As>
class Foo : public Foo<As...>
{
protected:
using Foo<As...>::foo;
public:
using Foo<As...>::bar;
void bar(const A& a) { foo(a); }
};
template <class A>
class Foo<A>
{
protected:
template <class T>
void foo(const T& t) { }
public:
void bar(const A& a) { foo(a); }
};
In a similar vain to Piotr Skotnicki's answer, this uses inheritance to build up a class with bar overloads for all of the template arguments. It's a bit cleaner though, with only one class template plus a partial specialization.

template<class A, class Foo_t>
class bar_t {
public:
void bar(const A &a) { Foo_t::foo(a); }
};
template<class ...As>
class Foo : bar_t<As, Foo<As...> >... {
protected:
template<class T>
void foo(const T& a) { /* do stuff */ }
};

Related

C++ conditional template member function

I am trying to understand how to use std::enable_if to choose between 2 functions implementation. In this case, if the type TupleOfCallback doesn't contains all the type, it will not compile because std::get<...> will throw an error.
For exemple:
Executor<Entity1*, Entity2*> task([](Entity1 *e){}, [](Entity2 *2){});
This will not compile because Entity3* is not part of the tuple.
It seem that we can choose between two functions with the same prototype,
void Exec(Entity3 *entity)
{
//enabled when Entity3* is **not** in the tuple
}
OR
void Exec(Entity3 *entity)
{
//enabled when Entity3 is in the tuple
std::get<std::function<void(Entity3*)>>(m_Callbacks)(entity);
}
But i dont understand how to achieve this goal.
C++ template mechanism is still hard for me, any help is welcome.
template<typename ...T>
class Executor
{
typedef std::tuple<std::function<void(T)>...> TupleOfCallback;
public:
Executor(const std::function<void(T)> &...func)
{
}
void Exec(Entity1 *entity)
{
std::get<std::function<void(Entity1*)>>(m_Callbacks)(entity);
}
void Exec(Entity2 *entity)
{
std::get<std::function<void(Entity2*)>>(m_Callbacks)(entity);
}
void Exec(Entity3 *entity)
{
std::get<std::function<void(Entity3*)>>(m_Callbacks)(entity);
}
public:
TupleOfCallback m_Callbacks;
};
Building on this one Check if parameter pack contains a type. You can use two traits to select which method to call:
#include <iostream>
#include <type_traits>
struct Entity1 {};
struct Entity2 {};
struct Entity3 {};
template<typename What, typename ... Args>
struct is_present {
static constexpr bool value {(std::is_same_v<What, Args> || ...)};
};
template<typename T>
struct is_entity : is_present<T,Entity1,Entity2,Entity3> {};
template <typename T, typename ...Args>
struct is_present_entity {
static constexpr bool value = is_present<T,Args...>::value && is_entity<T>::value;
};
template <typename T, typename ...Args>
struct is_not_present_entity {
static constexpr bool value = (!is_present<T,Args...>::value) && is_entity<T>::value;
};
template<typename ...T>
class Executor
{
public:
template <typename U, std::enable_if_t< is_present_entity<U,T...>::value,bool> = true>
void Exec(U* t){
std::cout << "foo\n";
}
template <typename U, std::enable_if_t< is_not_present_entity<U,T...>::value,bool> = true>
void Exec(U* t){
std::cout << "bar\n";
}
};
struct foo {};
int main(void) {
Executor<Entity1,Entity2> ex;
Entity1 e1;
ex.Exec(&e1);
Entity3 e3;
ex.Exec(&e3);
// foo f;
// ex.Exec(&f);
}
output:
foo
bar
Another C++17 option:
template <typename T>
class ExecutorLeaf
{
public:
std::function<void(T)> callback;
void Exec(T entity) { callback(entity); }
};
template <typename... Ts>
class Executor : ExecutorLeaf<Ts>...
{
public:
Executor(const std::function<void(Ts)>&...funcs) : ExecutorLeaf<Ts>{funcs}... {}
using ExecutorLeaf<Ts>::Exec...; // C++17
// Fallback
template <typename T> void Exec(T) {}
};
Demo
If you can guarantee that all types appear only once, then the following should work:
template<typename... Ts>
class Executor {
using TupleOfCallback = std::tuple<std::function<void(Ts)>...>;
public:
Executor(const std::function<void(Ts)>&... func);
template<class E>
std::enable_if_t<(std::is_same_v<Ts, E*> || ...)>
Exec(E* entity) {
std::get<std::function<void(E*)>>(m_Callbacks)(entity);
}
template<class E>
std::enable_if_t<!(std::is_same_v<Ts, E*> || ...)>
Exec(E* entity)
{ }
public:
TupleOfCallback m_Callbacks;
};
The basic idea is to use fold-expression to detect whether E* is included in Ts..., thereby enabling the corresponding function.
Demo.

SFINAE and inheritance

I'm looking for a solution to a following problem:
#include <string>
class A
{
public:
template <typename T>
static typename std::enable_if<std::is_same<T, std::string>::value, void>::type foo(T val)
{
printf("std::string\n");
}
template<typename T, typename... Arg>
static void multiple(Arg&&... arg)
{
T::foo(arg...);
}
};
class B : public A
{
public:
template <typename T>
static typename std::enable_if<std::is_same<T, int>::value, void>::type foo(T val)
{
printf("int\n");
}
};
int main()
{
std::string a;
int b = 0;
A::multiple<B>(a, b);
}
All works fine if both foo methods are in the same class or I force foo from proper class (A::foo for std::string and B::foo for int), however I need more than one class, because base class must be extendable. I can't use simple specialization, because I need more SFINAE features like detect for std::pair, std::tuple etc. I also don't want to move foo methods from a class to a namespace. Do you have any Idea how can I solve this issue?
Here B::foo hides A::foo, you need a using:
class B : public A
{
public:
using A::foo;
template <typename T>
static typename std::enable_if<std::is_same<T, int>::value, void>::type foo(T val)
{
printf("int\n");
}
};
But
From namespace.udecl#15.sentence-1:
When a using-declarator brings declarations from a base class into a derived class, member functions and member function templates in the derived class override and/or hide member functions and member function templates with the same name, parameter-type-list, cv-qualification, and ref-qualifier (if any) in a base class (rather than conflicting)
Return type doesn't count, so you have to use std::enable_if in parameter:
class A
{
public:
template <typename T>
static void foo(T val, std::enable_if_t<std::is_same<T, std::string>::value, int> = 0)
{
printf("std::string\n");
}
};
class B : public A
{
public:
using A::foo;
template <typename T>
static void foo(T val, std::enable_if_t<std::is_same<T, int>::value, int> = 0)
{
printf("int\n");
}
};
Demo
Note: you also have typo for
template<typename T, typename... Arg>
static void multiple(Arg&&... arg)
{
T::foo(arg...); // B::foo(string, int)
}
which should be
template<typename T, typename... Arg>
static void multiple(Arg&&... arg)
{
(T::foo(arg), ...); // B::foo(string), B::foo(int)
}

Template argument deduction failed with typedef?

Considering the following couple of classes:
template <typename T1, typename T2>
class A{
public:
// ...
};
template<typename _T>
struct alias { typedef A<int,_T> intA; };
class B{
public:
// ...
template <typename _T> B& operator=(const typename alias<_T>::intA& _arg) { };
};
When I try to assign an object of class A<int,int> to an object of class B, I get the following compilation error:
template argument deduction/substitution failed: couldn't deduce template parameter ‘_T’
Is there an alternative way to use something of a typedef as the input argument to B::operator=()??
templated using might fix the issue
template <typename T1, typename T2>
class A{
public:
// ...
};
template<typename _T>
using alias = A<int,_T>;
class B{
public:
// ...
template <typename _T> B& operator=(const alias<_T>& ) { return *this; };
};
void f()
{
B b;
A<int, int> a;
b = a;
}
The problem is that intA is a dependant name. Templates cannot be deduced from dependant names. See for example: Dependent Types: Template argument deduction failed.
You are also missing the typename keyword.
You can either explicitly specify the type for the operator:
template <typename T1, typename T2>
struct A{ };
template<typename _T>
struct alias { typedef A<int,_T> intA; };
struct B
{
template <typename T> B& operator=(const typename alias<T>::intA& _arg) { };
};
int main()
{
A<int,int> a;
B b;
b.operator=<int>(a);
return 0;
}
or you can have a specific, non-dependant-name parameter using a templated alias (with or without a function):
template <typename T1, typename T2>
struct A{ };
template<class T>
using alias_int = A<int, T>;
struct alias
{
template<class T>
using intA = A<int, T>;
};
struct B
{
template <typename T> B& operator=(const alias_int<T>& _arg) { };
};
struct C
{
template <typename T> C& operator=(const alias::intA<T>& _arg) { };
};
int main()
{
A<int,int> a;
B b;
C c;
b = a;
c = a;
return 0;
}
I'm getting a different error (using g++ 5.4):
need ‘typename’ before ‘alias<_T>::intA’ because ‘alias<_T>’ is a dependent scope
and true enough the following compiles for me:
template <typename T1, typename T2>
class A{
public:
// ...
};
template<typename _T>
struct alias { typedef A<int,_T> intA; };
class B{
public:
// ...
template <typename _T> B& operator=(const typename alias<_T>::intA& _arg) { };
};
I think the reason is that alias<_T>::intA isn't an actual type but a templated typename.

SFINAE and variadic template classes

I'm creating a class C that inherits from variable amount of classes. List of those classes is defined, for example: A,B. In function of class C I need to call functions from all base classes but objects can be C<A,B> , C<A>or C<B> so if I will call functions of class A in C<B> I will get an error. Here is example of the classes and how I've tried to solve problem:
class A
{
int a;
public:
virtual void set_a(const int &value)
{
a = value;
}
protected:
virtual int get_a()
{
return this->a;
}
};
class B
{
int b;
public:
virtual void set_b(const int &value)
{
b = value;
}
protected:
virtual int get_b()
{
return this->b;
}
};
template<class ...T>
struct Has_A
{
template<class U = C<T...>>
static constexpr bool value = std::is_base_of < A, U > ::value;
};
template<class ...T>
class C :
virtual public T...
{
public:
#define HAS_A Has_A<T...>::value
void f()
{
#if HAS_A<>
auto a = this->get_a();
#endif
auto b = this->get_b();
cout << HAS_A<>;
}
};
When I call f() of object C<A,B> it skips the call get_a() but output is true.
Initially, I wrote this
template<class U = C<T...>>
typename std::enable_if<!std::is_base_of<A, U>::value, int>::type get_a()
{
return -1;
}
template<class U = C<T...>>
typename std::enable_if<std::is_base_of<A,U>::value, int>::type get_a()
{
return A::get_a();
}
But I don't want to rewrite this for all functions of A and B. Let's assume that A has 10 more functions.
Is there any beautiful solution?
P.S Sorry for my English. I never used SFINAE before.
Basically I have bunch of genes and I want to write convenient wrap for them where one can configure genes that he wants organism to have.
In current standard, this is trivial:
void f() {
if constexpr(Has_A<T...>::value) {
auto a = get_a();
}
auto b = get_b();
}
If you can use C++17, the bipll's solution (if constexpr ()) is (IMHO) the better one.
Otherwise, C++11 or C++14, I'm not sure it's a good idea but I propose the following solution because it seems to me funny (and a little perverted).
First of all, instead of Has_A I propose a more generic isTypeInList
template <typename...>
struct isTypeInList;
template <typename X>
struct isTypeInList<X> : public std::false_type
{ };
template <typename X, typename ... Ts>
struct isTypeInList<X, X, Ts...> : public std::true_type
{ };
template <typename X, typename T0, typename ... Ts>
struct isTypeInList<X, T0, Ts...> : public isTypeInList<X, Ts...>
{ };
I also propose the use of the simple indexSequence
template <std::size_t...>
struct indexSequence
{ };
that is inspired to std::index_sequence that (unfortunately) is available only starting from C++14.
So, inside C<T...>, you can define the template using
template <typename X>
using list = typename std::conditional<isTypeInList<X, Ts...>{},
indexSequence<0u>,
indexSequence<>>::type;
so that list<A> is indexSequence<0> if A is part of the T... variadic list, indexSequence<> (empty sequence) otherwise.
Now you can write f() that simply call an helper function f_helper() that receive as many indexSequences as many types you need to check.
By example: if you need to know if A and B are part of the T... variadic list, you have to write f() as follows
void f ()
{ f_helper(list<A>{}, list<B>{}); }
Now f_helper() can be a private function and can be
template <std::size_t ... As, std::size_t ... Bs>
void f_helper (indexSequence<As...> const &,
indexSequence<Bs...> const &)
{
using unused = int[];
int a { -1 };
int b { -1 };
(void)unused { 0, ((void)As, a = this->get_a())... };
(void)unused { 0, ((void)Bs, b = this->get_b())... };
// do something with a and b
}
The idea is that As... is 0 if A is in T... or empty list otherwise.
So
int a { -1 };
initialize a with the value of your fake get_a().
With
(void)unused { 0, ((void)As, a = this->get_a())... };
is executed a = this->get_a(), only one time, iff (if and only if) A is in the T... variadic list.
The funny part of this solution is that a = this->get_a() isn't a problem when A isn't in the variadic list. Isn't there if As... is an empty list.
The following is a C++11 full working example (where I've renamed in Ts... the T... variadic sequence for C)
#include <utility>
#include <iostream>
#include <type_traits>
class A
{
private:
int a;
public:
virtual void set_a (int const & value)
{ a = value; }
protected:
virtual int get_a ()
{ std::cout << "get_a()!" << std::endl; return this->a; }
};
class B
{
private:
int b;
public:
virtual void set_b (int const & value)
{ b = value; }
protected:
virtual int get_b ()
{ std::cout << "get_b()!" << std::endl; return this->b; }
};
template <typename...>
struct isTypeInList;
template <typename X>
struct isTypeInList<X> : public std::false_type
{ };
template <typename X, typename ... Ts>
struct isTypeInList<X, X, Ts...> : public std::true_type
{ };
template <typename X, typename T0, typename ... Ts>
struct isTypeInList<X, T0, Ts...> : public isTypeInList<X, Ts...>
{ };
template <std::size_t...>
struct indexSequence
{ };
template <typename ... Ts>
class C : virtual public Ts...
{
private:
template <typename X>
using list = typename std::conditional<isTypeInList<X, Ts...>{},
indexSequence<0u>,
indexSequence<>>::type;
template <std::size_t ... As, std::size_t ... Bs>
void f_helper (indexSequence<As...> const &,
indexSequence<Bs...> const &)
{
using unused = int[];
int a { -1 };
int b { -1 };
(void)unused { 0, ((void)As, a = this->get_a())... };
(void)unused { 0, ((void)Bs, b = this->get_b())... };
// do something with a and b
}
public:
void f ()
{ f_helper(list<A>{}, list<B>{}); }
};
int main()
{
C<> c0;
C<A> ca;
C<B> cb;
C<A, B> cab;
std::cout << "--- c0.f()" << std::endl;
c0.f();
std::cout << "--- ca.f()" << std::endl;
ca.f();
std::cout << "--- cb.f()" << std::endl;
cb.f();
std::cout << "--- cab.f()" << std::endl;
cab.f();
}
I think you can do this with function-member-pointer.
call_if_base calls the given function-pointer only if baseT is the base of T. However all function-results are ignored and it requires at least one parameter.
template <class baseT, class T, typename funcT, class ...Args>
typename std::enable_if<std::is_base_of<baseT, T>::value, void>::type call_if_base(T& obj, funcT func, Args... args) {
(dynamic_cast<baseT&>(obj).*func)(args...);
}
template <class baseT, class T, typename funcT, class ...Args>
typename std::enable_if<!std::is_base_of<baseT, T>::value, void>::type call_if_base(T& obj, funcT func, Args... args) {
}
template<class ...T>
class C :
virtual public T...
{
public:
void set(const int &value) {
call_if_base<A, C>(*this, &A::set_a, 0);
call_if_base<B, C>(*this, &B::set_b, 5);
}
};
or as member-functions
template<class ...T>
class C :
virtual public T...
{
public:
void set(const int &value) {
call_if_base<A>(&A::set_a, 0);
call_if_base<B>(&B::set_b, 5);
}
protected:
template <class baseT, typename funcT, class ...Args>
typename std::enable_if<std::is_base_of<baseT, C>::value, void>::type call_if_base(funcT func, Args... args) {
(dynamic_cast<baseT&>(*this).*func)(args...);
}
template <class baseT, typename funcT, class ...Args>
typename std::enable_if<!std::is_base_of<baseT, C>::value, void>::type call_if_base(funcT func, Args... args) {
}
};

c++ template tricky partial specialization const+template member

I have template struct declared as:
template <bool sel_c>
struct A
{
A(){/*...*/}
enum{
is_straight = sel_c
};
typedef A<sel_c> this_t;
typedef A<!sel_c> oposit_t;
A(const this_t& copy){/*...*/}
A(const oposit_t& copy){/*...*/}
~A(); //will be specialized latter for true/false
template <class T> //this is my pain !
void print(T& t);
};
How can I declare specializations of both print methods?
I have already tried following (with error: error C2244: 'A::print' : unable to match function definition to an existing declaration )
template <class T>
void A<false>::print(T& t)
{
/*...*/
}
And following (with error that no copy constructor declared early above):
template <> struct A<false>
{
~A()
{
/*...*/
}
template <class T>
void print(T& t)
{
/*...*/
}
};
template<>
template< class T >
void A<false>::print( T& t ) {}
I don't see any problem with your second solution, the following compiles just fine with g++:
template <bool sel_c>
struct A
{
A(){/*...*/}
enum{
is_straight = sel_c
};
typedef A<sel_c> this_t;
typedef A<!sel_c> oposit_t;
A(const this_t& copy){/*...*/}
A(const oposit_t& copy){/*...*/}
~A(); //will be specialized latter for true/false
template <class T> //this is my pain !
void print(T& t);
};
template <>
struct A<false>
{
~A(){};
template <class T>
void print(T& t) {}
};
template <>
struct A<true>
{
~A(){};
template <class T>
void print(T& t) {}
};
int main(int argc, char** argv)
{
A<false> a1;
A<true> a2;
}
EDIT: this is incomplete, see comments