Home > OS >  an array of non-coherent types, that have something in common (array of concepts)
an array of non-coherent types, that have something in common (array of concepts)

Time:03-08

I think the use case is frequent, when you have multiple templated classes that have an element (variable or fcn) in common, and you want to call the fcn for all of them in a loop-like way.

Clearly, we can define a base class and make a list of base-class pointers, and use them to loop, but I am trying to avoid pointers (for copy problems) and virtual functions (for optimization reasons)

template <typename T> 
struct A {T _value; void foo(){cout<<_value;}};

A<int> a_1{1}; A<float> a_2{2.0f}; ...

void foo_all(){ a_1.foo(); a_2.foo(); ... }

// for (auto i :{a_1,a_2, ...}) is not possible
// array<A<T>,10>; is not also possible, if T is variable

Is some sort of design pattern/ idiom known for this use case Is it planned to have an iteratable container for concepts some when in the future?

CodePudding user response:

Trying variadic template?

template <typename T, typename... Types>
void callAll(T&& value, Types&&... values) {
    value.foo();
    if constexpr (sizeof...(values) > 0) {
        callAll(values...);
    }
}

And then

callAll(a_1, a_2);

Demo

If you're using C 20, you can use concepts to restrict the argument type.

template<typename T>
concept IsA = requires(T x)
{
    { x.foo() };
};

template <typename T, typename... Types>
requires IsA<T>
void callAll(T&& value, Types&&... values)

CodePudding user response:

I kind of found a solution by implementing my own tuple (without allocation)

template <typename T1, typename... Tn> struct tuple
{
    tuple(T1&& first, Tn&&... rest): m_first(first), m_rest(std::forward<Tn>(rest)...){};
    T1 m_first; tuple<Tn...> m_rest;
};

template <typename T> struct tuple<T>  /*specialization*/
{ 
    tuple(T&& first): m_first(first){};
    T m_first; 
};

template<class functor,typename... Tn>
void apply(functor&& fcn, tuple<Tn...>& t) 
{ 
    fcn(t.m_first); 
    if constexpr(sizeof...(Tn)>1) apply(std::forward<functor>(fcn), t.m_rest); 
};
  • Related