Home > Blockchain >  Push back string into vector<T>
Push back string into vector<T>

Time:11-11

I'm finally trying to learn templates and I created a template function that will return an std::vector with a generic type.

When compiling I get an error:

error: no matching function for call to ‘std::vector::push_back(std::string&)’

Is there a way to support std::string or a comparable type in the template vector in addition to the primitive types?

Here is a 'Minimal, Reproducible Example' that doesn't compile due to this error (this is obviously not my code, it just illustrates the error):

#include <iostream>
#include <vector>

enum types{
    TINT = 0,
    TDOUBLE = 1,
    TSTRING = 2,
};

class TestClass{
    public:

    template<typename T> std::vector<T> getData(types type)
        {
            std::vector<T> entries;

            int i_value;
            double d_value;
            std::string st_value;

            switch (type)
            {
                case types::TINT:
                    i_value = 1;
                    entries.push_back(i_value);
                    break;
                case types::TDOUBLE:
                    d_value = 0.1;
                    entries.push_back(d_value);
                    break;
                case types::TSTRING:
                    st_value = "foo";
                    entries.push_back(st_value); //Pushing an std::string causes a compile error
                    break;
                default:
                    break;
            }

        return entries;
    }
};

int main()
{
    TestClass bar;
    std::vector<int> test = bar.getData<int>(types::TINT);

    return 0;
}

Commenting the line entries.push_back(st_value); makes everything compile again.

CodePudding user response:

The code does not compile because you try to check the types at runtime. This is too late. Use std::is_same to make a compile time check.

template<typename T> std::vector<T> getData()
{
    std::vector<T> entries;

    int i_value;
    double d_value;
    std::string st_value;

    if constexpr(std::is_same_v<T, int>) {
        i_value = 1;
        entries.push_back(i_value);
    }
    else if constexpr(std::is_same_v<T, double>) { 
        d_value = 0.1;
        entries.push_back(d_value);
    }
    else if constexpr(std::is_same_v<T, std::string>) {
        st_value = "foo";
        entries.push_back(st_value);
    }
    return entries;
}

CodePudding user response:

This line std::vector<int> test = bar.getData<int>(types::TINT); caused the compiler to expand the function to be:

    // Note: T becomes int
    std::vector<int> getData(types type)
        {
           // Note: T becomes int
            std::vector<int> entries;

            int i_value;
            double d_value;
            std::string st_value;

            switch (type)
            {
                case types::TINT:
                    i_value = 1;
                    entries.push_back(i_value);
                    break;
                case types::TDOUBLE:
                    d_value = 0.1;
                    entries.push_back(d_value);
                    break;
                case types::TSTRING:
                    st_value = "foo";
                    entries.push_back(st_value); //Pushing an std::string causes a compile error
                    break;
                default:
                    break;
            }

        return entries;
    }

Which means, entries is a vector of integers. It cannot take a std::string object.

  • Related