首页 > 解决方案 > Why does the string version of this template function compile but the float version doesn't?

问题描述

I don't have much experience with templating in C++, but I know it can be very handy and am trying to use it more.

I created the following example code which does not compile, with the compiler complaining about potentially assigning a string to a float on line 19. I think I understand that error, but if I change the instantiation of the template on line 39 from floats to strings (so vector<string> scales = line_to_vector<string>("0.0 1.0 2.0 3.0")), the code compiles and runs correctly. Why does this version not generate a compiler error on line 17, since the string instantiation would compile that line to assign a float to a string?

#include <string>
#include <vector>
#include <iostream>
#include <typeinfo>

using namespace std;

template <class T>
vector< T > line_to_vector(string line, string sep=" ")
{
    vector< T > input_set;
    size_t pos = line.find(sep);
    T buf;
    while( pos != string::npos )
    {
        if(is_same<T, float>::value)
            buf = stof(line.substr(0, pos));
        else if(is_same<T, string>::value)
            buf = line.substr(0, pos);
        else
        {
            cerr << "Can't process line of type " << typeid(T).name()
                 << ". Please choose float or string." << endl;
            return input_set;
        }

        input_set.push_back(buf);
        if( line.length() )
        {
            pos = line.find(sep);
            line = line.substr(pos+1);
        }
    }
    return input_set;
}

int main()
{
    vector<float> scales = line_to_vector<float>("0.0 1.0 2.0 3.0");
    for(size_t i=0; i<scales.size(); i++)
        cout << scales[i] << ", ";
    cout << endl;
    return 0;
}
prompt > g++ comp_err.cc
comp_err.cc:19:19: error: assigning to 'float' from incompatible type 'std::__1::basic_string<char>'
            buf = line.substr(0, pos);
                  ^~~~~~~~~~~~~~~~~~~
comp_err.cc:39:28: note: in instantiation of function template specialization 'line_to_vector<float>' requested here
    vector<float> scales = line_to_vector<float>("0.0 1.0 2.0 3.0");
                           ^
1 error generated.

I can avoid this problem entirely if I just drop the templating (this is a simple-enough situation to not really require it), but I want to understand what is going on here.

标签: c++templates

解决方案


您似乎在以迂回的方式询问为什么将浮点数分配给字符串没有错误,例如:

#include <string>

int main()
{
    std::string x;
    x = 5.5f;
}

答案是这会调用赋值运算符重载(此处为 #4):

basic_string& operator=( CharT ch );

存在从floatto的隐式转换char,行为是将字符串设置为仅包含该字符。

事后看来,这并不是一个伟大的设计决定,而是std::string在 20 多年前设计的,当时还没有预见到今天的语言演变。


推荐阅读