現在、このチュートリアルで指定されているクラスを使用しています: http://www.dreamincode.net/forums/topic/183191-create-a-simple-configuration-file-parser/
最初は問題なく動作しましたが、単一のソース ファイルを個別のヘッダー ファイルと cpp ファイルに分割して以来、getValueOfKey 関数を呼び出すことができませんでした。
ヘッダ:
#ifndef CONFIGFILE_H
#define CONFIGFILE_H
#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <fstream>
#include <typeinfo>
class ConfigFile
{
private:
std::map<std::string, std::string> contents;
std::string fName;
void removeComment(std::string &line) const;
bool onlyWhitespace(const std::string &line) const;
bool validLine(const std::string &line) const;
void extractKey(std::string &key, size_t const &sepPos, const std::string &line) const;
void extractValue(std::string &value, size_t const &sepPos, const std::string &line) const;
void extractContents(const std::string &line);
void parseLine(const std::string &line, size_t const lineNo);
void ExtractKeys();
public:
ConfigFile(const std::string &fName);
bool keyExists(const std::string &key) const;
template <typename ValueType>
ValueType getValueOfKey(const std::string &key, ValueType const &defaultValue) const;
};
#endif /* CONFIGFILE_H */
cpp:
#include "ConfigFile.h"
std::map<std::string, std::string> contents;
std::string fName;
template <typename T>
static std::string T_to_string(T const &val)
{
std::ostringstream ostr;
ostr << val;
return ostr.str();
}
template <typename T>
static T string_to_T(std::string const &val)
{
std::istringstream istr(val);
T returnVal;
if (!(istr >> returnVal))
std::cout << "CFG: Not a valid " << (std::string)typeid (T).name() << " received!\n" << std::endl;
return returnVal;
}
template <>
std::string string_to_T(std::string const &val)
{
return val;
}
void ConfigFile::removeComment(std::string &line) const
{
if (line.find(';') != line.npos)
line.erase(line.find(';'));
}
bool ConfigFile::onlyWhitespace(const std::string &line) const
{
return (line.find_first_not_of(' ') == line.npos);
}
bool ConfigFile::validLine(const std::string &line) const
{
std::string temp = line;
temp.erase(0, temp.find_first_not_of("\t "));
if (temp[0] == '=')
return false;
for (size_t i = temp.find('=') + 1; i < temp.length(); i++)
if (temp[i] != ' ')
return true;
return false;
}
void ConfigFile::extractKey(std::string &key, size_t const &sepPos, const std::string &line) const
{
key = line.substr(0, sepPos);
if (key.find('\t') != line.npos || key.find(' ') != line.npos)
key.erase(key.find_first_of("\t "));
}
void ConfigFile::extractValue(std::string &value, size_t const &sepPos, const std::string &line) const
{
value = line.substr(sepPos + 1);
value.erase(0, value.find_first_not_of("\t "));
value.erase(value.find_last_not_of("\t ") + 1);
}
void ConfigFile::extractContents(const std::string &line)
{
std::string temp = line;
temp.erase(0, temp.find_first_not_of("\t "));
size_t sepPos = temp.find('=');
std::string key, value;
extractKey(key, sepPos, temp);
extractValue(value, sepPos, temp);
if (!keyExists(key))
contents.insert(std::pair<std::string, std::string > (key, value));
else
std::cout << "CFG: Can only have unique key names!\n" << std::endl;
}
void ConfigFile::parseLine(const std::string &line, size_t const lineNo)
{
if (line.find('=') == line.npos)
std::cout << "CFG: Couldn't find separator on line: " << T_to_string(lineNo) << "\n" << std::endl;
if (!validLine(line))
std::cout << "CFG: Bad format for line: " << T_to_string(lineNo) << "\n" << std::endl;
extractContents(line);
}
void ConfigFile::ExtractKeys()
{
std::ifstream file;
file.open(fName.c_str());
if (!file)
std::cout << "CFG: File " << fName << " couldn't be found!\n" << std::endl;
std::string line;
size_t lineNo = 0;
while (std::getline(file, line))
{
lineNo++;
std::string temp = line;
if (temp.empty())
continue;
removeComment(temp);
if (onlyWhitespace(temp))
continue;
parseLine(temp, lineNo);
}
file.close();
}
ConfigFile::ConfigFile(const std::string &fName)
{
this->fName = fName;
ExtractKeys();
}
bool ConfigFile::keyExists(const std::string &key) const
{
return contents.find(key) != contents.end();
}
template <typename ValueType>
ValueType ConfigFile::getValueOfKey(const std::string &key, ValueType const &defaultValue = ValueType()) const
{
if (!keyExists(key))
return defaultValue;
return string_to_T<ValueType> (contents.find(key)->second);
}
のような単一のファイルの場合と同じ方法を使用して呼び出そうとしていますstd::cout << Config.getValueOfKey<std::string>("test");
が、次のコンパイラエラーが発生しています
main.cpp: In function 'int main(int, char**)':
main.cpp:29:71: error: no matching function for call to 'ConfigFile::getValueOfKey(const char [5])'
main.cpp:29:71: note: candidate is:
In file included from main.h:17:0,
from main.cpp:9:
ConfigFile.h:35:12: note: template<class ValueType> ValueType ConfigFile::getValueOfKey(const string&, const ValueType&) const
ConfigFile.h:35:12: note: template argument deduction/substitution failed:
main.cpp:29:71: note: candidate expects 2 arguments, 1 provided
テンプレートの理解が不十分なため、このエラーが何を伝えようとしているのか実際にはわかりません。char配列の代わりに直接文字列を渡そうとしましたが、役に立ちませんでした。助けや説明があれば大歓迎です。私の頭は、過去数時間で机にすてきな穴を開けました。