mercredi 20 mai 2020

c++11 how to check template parameter pack has N args before calling function with N args

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?

Aucun commentaire:

Enregistrer un commentaire