0

I have this code, which fills my row structure with string data for each column.

    struct row_t
    {
        row_t()
        {};
        template<typename ...T>
        row_t(const T& ...var)
        {
            append(var...);
        }
        template<typename T, typename ...Types>
        void append(const T &var1, const Types& ...var2)
        {
           // here should be some kind of check, that number of arguments == COLUMN_COUNT
            data.append_copy(var1);
            append(var2...);
        }
        template<typename T>
        void append(const T &var1)
        {
            data.append_copy(var1);
        }

        array_local_t<sstring_t, COLUMN_COUNT> data; // my implementation of arrays
    };

and I can call is like this:

row_t tmp_row(a,b,c,d);
//with a, b, c, d being my sstring_t types

Now, as you might noticed, my data array is of type sstring_t. So If i tried to call this with a,b,c,d being int, I would not be able to compile the code -> I don't need or want the template functions to be of Typename T, but only sstring_t, because that is the only thing that makes sense in my case (so I dont want to change data array to type T and call it a day). I was only able to write the code like this. Can you help me to convert it to specific type only(sstring_t) using C++11 max?

cigien
  • 57,834
  • 11
  • 73
  • 112
  • related/dupe: https://stackoverflow.com/questions/30346652/enforce-variadic-template-of-certain-type – NathanOliver Sep 14 '20 at 16:00
  • `static_assert(std::is_same::type, sstring_t>::value);` in the constructor?? – JeJo Sep 14 '20 at 16:04
  • As you said, if you try to pass in `int`s you get a compile-time error. So why do you need to rerewririte it at all? Using a `static_assert` could give you a more clear error message if that is the issue. – super Sep 14 '20 at 16:14
  • 1
    Your code already only works with `sstring_t` due to implementation, Do you really want/need to be SFINAE friendly? – Jarod42 Sep 14 '20 at 16:15
  • `std::initializer_list` is also an alternative to variadic. – Jarod42 Sep 14 '20 at 16:17
  • It seems like initializer_list is the right way how to do what I want. Thanks. But I still want to know if it is even possible to do how I imagined it. The proposed solutions within the duplicate link states, that I should make the general template and then add conditions, that would prevent the code from being generated with given unwanted parameters.. But I would like to have a solution that just simply states exactly what is allowed (sstring_t). I am not saying those solutions are not right to do what I need, I just want to understand templates and variadic templates better. – Michael Očenášek Sep 14 '20 at 22:17
  • I have added an answer as another possible way how to do this. – Michael Očenášek Sep 14 '20 at 23:02

1 Answers1

0

After some additional searching I found this link Which proposes a simple, but good logic how to get what I want with just a slight modification of my code. (I modified it to use vector so I could test it outside of work)

    struct row_t
    {
        row_t()
        {};
        template<typename ...Types>
        row_t(const string &var1, const Types& ...var2)
        {
           // here should be some kind of check, that number of arguments == COLUMN_COUNT
            append(var1, var2...);
        }
       
        template<typename ...Types>
        void append(const string &var1, const Types& ...var2)
        {
            data.push_back(var1);
            append(var2...);
        }

        void append(const string &var1)
        {
            data.push_back(var1);
        }

        vector<string> data;
    };

With this code, the only options for compiler when you try to call row_t row("something",2,3) or row(some_type, other_type, third_type) etc.. Is try to convert the given arguments to string. Because it can pick append with one string as argument, or append with string as first argument and some "possibly" other arguments... which due to induction have to be string as well.

I might have not been clear enough with my original question. The goal was to modify the code in a way that only valid call of the row_t constructor would be with string arguments. The code provided in the question was not compilable for other types, but it was because of the data type of row.data being string not because the template would not allow it. The code in this answer would fail on template append functions if provided with non-string arguments, not on push to row.data of wrong type.

  • As we said, `data.push_back(var1);` already spot the invalid argument, now, you would have error on `append(var2...);` line instead. – Jarod42 Sep 16 '20 at 15:13