0

By using c++ 14 or c++11, do we have an elegant approach to do the following task? Number of members and type of operations are determined by the template input value 'count'

    template<int count>
    class show{
    public:
        run(){
            if (count == 1){
                int x;
            } else if(count ==2){
                int x, y;
            }else if(count ==3){
                int x, y, z;
            } 

            if (count == 1){
                printf("res: %d \n", x);
            } else if(count ==2){
                printf("res: %d \n", x+y);
            }else if(count ==3){
                printf("res: %d \n", x+y+z);
            } 

        }
    };

Update: can we use partial specialization or something related to the template in this case?

  • do you mean [if constexpr](https://godbolt.org/z/bhT7ozxGb), i.e. compile-time if or sth else? – alagner Dec 17 '21 at 07:58
  • Is partial specialization useful for this case? I'm not familiar with this... – picklesmithy129 Dec 17 '21 at 08:00
  • 1
    if you want every member be separate variable, did you consider https://en.cppreference.com/w/cpp/types/enable_if? And enable it if count is <= # then idx of member (similar for for multiple run() definitions when count == # ) if not, you could create std::array of count size – stribor14 Dec 17 '21 at 08:05
  • sure, why not https://godbolt.org/z/6fdjj1j3c `if constexpr` should be equivalent to this though (provided you're on C++17 or newer; specialization is needed if you're limited to C++14), it's a matter of taste and one's needs to use one or the other. Could you provide more details to your problem? – alagner Dec 17 '21 at 08:05
  • If all are of same type, why not have a `vector` with size `count` and just sum it up? – Wander3r Dec 17 '21 at 08:22

2 Answers2

2

In your case, an array (std::array) seems appropriate:

template <std::size_t count>
class show
{
public:
    std::array<int, count> data{};
    // ...
    void run()
    {
        const int sum = std::accumulate(data.begin(), data.end(), 0);
        printf("res: %d \n", sum);
    }
};
Jarod42
  • 203,559
  • 14
  • 181
  • 302
2

Yes, you can use specialization:

template<int count>
class show;

template<>
class show<1>{
    int x;
    public:
    show(int _x):x{_x}{}
    void run(){
        std::cout << "val of x " << x << std::endl;
    }   
};



template<>
class show<2>{
    int x,y;
    public:
    show(int _x, int _y):x{_x}, y{_y}{}
    void run(){
        std::cout << "add " << x+y << std::endl;
    }   
};

But you also can have it more generic:

template <int count>
class simply
{
    std::array<int, count> arr;

    public:
    template < typename ... T > 
        simply( T ... in ): arr{ in... } {}

    void run()
    {   
        std::cout << [this](){ int sum=0; for( auto el: arr ){ sum+=el; } return sum; }() << std::endl;
    }   
};

To use all the stuff above:

int main() {
    show<1> s1(10);
    show<2> s2(100,200);

    s1.run();
    s2.run();

    simply<4> si( 1,2,3,4 );
    si.run();
}

Remarks: You should add some more stuff to simply to check that all parameters of type int with sfinae or static_assert. But his is another question ...

Klaus
  • 24,205
  • 7
  • 58
  • 113