0

Following on from this extracting a template parameter pack with different types into a vector of doubles produces warnings and cigien's answer.

I have the following code:

enum class p_type {p1, p2, p3};

class testerx
{
public:
    void process1(double a)
    {
        std::cout << "1" << a << std::endl;
    };
    void process2(double a, double b)
    {
        std::cout << "2" << a << " " << b << std::endl;
    };
    void process3(double a, double b, double c)
    {
        std::cout << "3" << a << " " << b << " " << c << std::endl;
    };
};

// The template type
template<typename TESTER, typename... ARGS>
class tester_templatex
{
public:
    explicit tester_templatex(p_type type) : m_type(type) {};

    void process(ARGS... args)
    {
        // Create a vector to put the args into. use double since that can hold all of the types
        // that I am using
        size_t param_count = sizeof...(args);
        std::cout << "PARAM COUNT X " << param_count << std::endl;

        std::vector<double> args_vect = {static_cast<double>(args)...};
        for (auto arg : args_vect)
        {
            std::cout << "arg: " << arg << std::endl;
        }

        // Now call the tester
        std::cout << "running tester: ";
        switch (m_type)
        {
            case p_type::p1:
                if constexpr (sizeof...(args) == 1)
                    m_tester.process1(args...);
                break;
            case p_type::p2:
                if constexpr (sizeof...(args) == 2)
                    m_tester.process2(args...);
                break;
            case p_type::p3:
                if constexpr (sizeof...(args) == 3)
                    m_tester.process3(args...);
                break;
        }
        std::cout << std::endl;
    };

    p_type m_type;
    TESTER m_tester;
};

main:

int main() {
    tester_templatex<testerx, int> templatex1(p_type::p1);
    tester_templatex<testerx, int, double> templatex2(p_type::p2);
    tester_templatex<testerx, int, double, int> templatex3(p_type::p3);
    templatex1.process(4);
    templatex2.process(4, 5.123);
    templatex3.process(4, 5.123, 6);

    return 0;
}

Here I have test class with 3 different functions. I have a template class which picks the function to call based on the p_type (bad name - dont ask!).

This works for c++17 compiled code. But I only have c++11 where I need to run this code. c++11 does not support if constexpr:

            case p_type::p3:
                if constexpr (sizeof...(args) == 3)
                    m_tester.process3(args...);
                break;

Without the if constexpr I get errors that the m_tester.process1/2/3 functions that don't match the parameter pack because they don't have the right number of parameters.

  • How can I fix this for c++11? - is it possible with a similar method?
  • Is there another way to extract N arguments from a parameter pack in c++11? - or some sort of type traits check?
code_fodder
  • 15,263
  • 17
  • 90
  • 167

1 Answers1

1

For each of your functions have an overload that does nothing:

template<typename... ARGS>
void process3(ARGS&...) { }

and then just call the function without testing for the size of the pack:

case p_type::p3:
    m_tester.process3(args...);
    break;

This should pick the non-templated function when there are suitably many arguments, and the function template in other cases.

j6t
  • 9,150
  • 1
  • 15
  • 35
  • (oops hit enter) I would like to hold out for a way to do it purley within the template function if possible, then I don't have to add these overload templates to other areas of me (real) code. But this is really nice alt if I cant get that – code_fodder May 20 '20 at 07:02
  • I don't think there is a solution that gets away without overloading if you don't have `if constexpr`. If you don't want to extend other classes, you can only add a proxy function call that *is* overloaded. – j6t May 20 '20 at 07:05
  • I *thought* (but can't quite put it together) there was some sort of way to check if a function has certain qualities (like `has_n_params`), in the way that you can use type_traits to only call a function if it is a bool function (probably explaining this badly as I have never a manged to do this yet!) like: https://en.cppreference.com/w/cpp/types/enable_if - but looking back at it does appear to be using overloads (I still struggle to read heavily templated code!)... so damn, now that makes sense! – code_fodder May 20 '20 at 07:19