canellas
canellas

Reputation: 697

variadic template only using type parameter

I would like to do something like this:

#include <iostream>

class a {

public:
    a() : i(2) {}

    template <typename ...ts>
    void exec() {
        f<ts...>();
        std::cout << "a::()" << std::endl;
    }

    int i;
private:

    template <typename t>
    void f() {
        i += t::i;
    }

    template <typename t, typename ...ts>
    void f() {
        f<t>();
        f<t, ts...>();
    }
};

struct b {
    static const int i = -9;
};

struct c {
    static const int i = 4;
};


int main()
{
    a _a;

    _a.exec<b,c>();

    std::cout << _a.i << std::endl;
}

The idea is to get the same information from a group of classes, without the need of an object of each class.

Does anyone know if it is possible?

Thanks!

Upvotes: 3

Views: 119

Answers (3)

Piotr Siupa
Piotr Siupa

Reputation: 4838

Reasons why your code is not compiling:

  1. Syntax of specializing templates is a little different.
  2. You need to put the most general case first.
  3. You can't partially specialize functions, only classes.
  4. Partial specialization is not allowed within classes, only in namespaces.

Here is an example for C++11.

#include <iostream>

template<typename t, typename ...ts>
class a {
public:
    static constexpr int x = t::i + a<ts...>::x;
};

template<typename t>
class a<t> {
public:
    static constexpr int x = 2 + t::i;
};

struct b {
    static constexpr int i = -9;
};

struct c {
    static constexpr int i = 4;
};

int main()
{
    constexpr int result = a<b,c>::x;
    std::cout << result << std::endl;
}

Remember that templates are calculated during compilation so, for optimization sake, it is a good idea to write them in a way that allows them to be constexpr.

Upvotes: 1

bartop
bartop

Reputation: 10315

In case Your compiler does not support C++17:

template <typename ...ts>
void f() {
    for ( const auto &j : { ts::i... } )
        i += j;
}

Upvotes: 5

Jarod42
Jarod42

Reputation: 217235

In C++17, your class would simply be

class a {

public:
    a() : i(2) {}

    template <typename ...ts>
    void exec() {
        ((i += ts::i), ...); // Folding expression // C++17
        std::cout << "a::()" << std::endl;
    }

    int i;
};

Possible in C++11 too, but more verbose.

Upvotes: 3

Related Questions