0

I have the following class template which has a member variable whose type is determined by the template argument. I want to initialize the value of this member in the constructor, which only takes a std::string. Thus, my problem is that I need to convert std::string to any of several types (int, double, bool, string). I don't think I can specialize just the constructor, and I would rather not specialize the entire class for each type. The problem with my code below is that stringstream stops streaming out when it hits a space:

#include <iostream>
#include <string>
#include <sstream>

using namespace std;

template <typename Ty>
struct Test
{
    Ty value;

    Test(string str) {
        stringstream ss;
        ss.str(str);
        ss >> value;
    }
};


int main()
{
    Test<int> t1{"42"};
    Test<double> t2{"3.14159"};
    Test<string> t3{"Hello world"};

    cout << t1.value << endl << t2.value << endl << t3.value << endl;

    return 0;
}

The output of the above code is:

42
3.14159
Hello

instead of "Hello world". Is there some way to get stringstream to not stop at whitespace, or some other device that will do arbitrary conversions like I need?

1

1 Answer 1

1

This works for me. Just declare a special implementation before the generalized implementation:

#include <iostream>
#include <string>
#include <sstream>

template<typename T>
struct Test {
    T value;
    Test(std::string);
};

template<>
inline Test<std::string>::Test(std::string str) {
    value = str;
}

template<typename T>
inline Test<T>::Test(std::string str) {
    std::stringstream ss;
    ss.str(str);
    ss >> value;
}

int main() {
    Test<int> t1{"42"};
    Test<double> t2{"3.14159"};
    Test<std::string> t3{"Hello world"};

    std::cout
        << t1.value << std::endl
        << t2.value << std::endl
        << t3.value << std::endl;

    return 0;
}

Here is an ideone working example.

Sign up to request clarification or add additional context in comments.

3 Comments

Hey, this works. I didn't know you could specialize the constructor without specializing the whole class. The key is not defining the constructor in the class at all; the general case and the specializations all go outside. On a side note, as a consequence of specializing outside of the class, I had to mark both versions of my constructor inline to avoid multiple definition errors.
If it's defined in a header, yes you need to do that. I'll update my answer. Also realized that some compilers require template<> (perhaps with C++ 14) before the specialized definition, so updating that too
Yes, GCC 4.9.3 required template<>. Forgot to mention that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.