Я думаю, что ваш базовый подход неверен.
Похоже, вы пытаетесь использовать шаблон-метапрограммирование для достижения своих целей.
Это, вероятно, не очень хорошая идея.
Более простой подход - просто использовать потоки C ++.
Эти потоковые объекты уже знают, как читать все основные типы. И любой, кто хочет что-либо делать в C ++, добавит соответствующие операторы ввода и вывода для потоковой передачи своего класса; поэтому довольно универсально, что вы сможете читать любой тип как ключ, так и значение (с ограничением, что он должен помещаться в одну строку).
Так что теперь вам просто нужно использовать стандартную шаблонную логику для определения оператора, который будет читать два объекта разных типов в одной строке.
Попробуйте это:
#include <string>
#include <memory>
#include <fstream>
#include <sstream>
#include <vector>
#include <iterator>
#include <algorithm>
// These can be any types.
typedef std::string Key;
typedef int Value;
// The data type to hold the data.
template<typename K,typename V>
class Data: public std::pair<K, V>
{
};
Вот код, который будет читать одну запись из одной строки файла:
Обратите внимание, что тип данных Data
и этот оператор ввода являются шаблонными и, таким образом, могут готовить пары ключ / значение любых объектов (если эти объекты знают, как выполнять потоковую передачу).
template<typename K,typename V>
std::istream& operator>>(std::istream& stream, Data<K,V>& data)
{
// Read a line into a local string.
std::string line;
std::getline(stream,line);
// convert the line into a stream and read the key/value from the line
std::stringstream linestream(line);
linestream >> data.first >> data.second;
// If the linestream is bad, then reading the key/value failed
// If reading one more `char` from the linestream works then there is extra crap in the line
// thus we have bad data on a line.
//
// In either case set the bad bit for the input stream.
char c;
if ((!linestream) || (linestream >> c))
{
stream.setstate(std::ios::badbit);
}
// return the stream.
return stream;
}
Теперь использовать его просто означает использовать поток:
int main()
{
// The input file
std::ifstream file("Plop");
// We will convert the file and store it into this vector.
std::vector<Data<Key,Value> > data;
// Now just copy the data from the stream into the vector.
std::copy(std::istream_iterator<Data<Key,Value> >(file),
std::istream_iterator<Data<Key, Value> >(),
std::back_inserter(data)
);
}
Примечание. В приведенном выше примере ключ должен быть одним словом (так как он читается с использованием строки). Если вам нужен ключ в виде строки, содержащей пробел, вам нужно проделать дополнительную работу. Но это тема другого вопроса.