Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
539 views
in Technique[技术] by (71.8m points)

c++ - Error C2664: Cannot convert argument from initializer list to std:initializer list

I have a function read() that reads a file and store information into a map. However, whenever the function calls map.insert(), it gives me an error.

Employee and Volunteer are two customs classes with only a few variables. For example, If I call

ifstream fin;
std::map<std::string, Employee*> employees;
fin.open("Employee.txt");
read<Employee, EMPLOYEE_SIZE>(fin, employees);

It gives the following error:

std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::insert(std::initializer_list<std::pair<const std::string,Employee *>>)': cannot convert argument 1 from 'initializer list' to 'std::initializer_list<std::pair<const std::string,Employee *>>'`. 

Here is the function(Both Employee and Volunteer has the same base class:)

template <typename T, int T_LINE_SIZE>
inline void read(std::ifstream& in, std::map<std::string, T*>& input) {
    std::string name = "";
    std::string ID="";
    std::string line;
    double salary;
    while (getline(in,line)) {
        if (typeid(T) == typeid(Volunteer)) {
            name = line.substr(0, 19);
            ID = line.substr(20, T_LINE_SIZE);
            input.insert({name,new Volunteer(ID,name)}); //error happens here
        }else if (typeid(T) == typeid(Employee)) {
            name = line.substr(0, 19);
            ID = line.substr(20, 29);
            salary = std::stod(line.substr(30, T_LINE_SIZE));
            input.insert({ name,new Employee(ID, name, salary) }); //error happens here
        }
    }
}

What am I doing wrong here?

question from:https://stackoverflow.com/questions/65879925/error-c2664-cannot-convert-argument-from-initializer-list-to-stdinitializer-li

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Try following code:

template <typename T, int T_LINE_SIZE>
inline void read(std::ifstream& in, std::map<std::string, T*>& input) {
    std::string name = "";
    std::string ID="";
    std::string line;
    double salary;
    while (getline(in,line)) {
        if constexpr (std::is_same<T, Volunteer>::value) {
            name = line.substr(0, 19);
            ID = line.substr(20, T_LINE_SIZE);
            input.insert({name,new Volunteer(ID,name)}); 
        }else if constexpr (std::is_same<T, Employee>::value) {
            name = line.substr(0, 19);
            ID = line.substr(20, 29);
            salary = std::stod(line.substr(30, T_LINE_SIZE));
            input.insert({ name,new Employee(ID, name, salary) }); 
        }
    }
}

The reason is that you are using templates. Based on the type of T when you call read() function, type of T is incorrect in scope of one if condition for calling insert() method. This happens because all possible outcomes of code need to be checked at compile time for different types. But when you use if constexpr, that part of code is ignored at compile time, so incorrect part of code will not be seen during compiling code and your code compiles correctly.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...