タイトルに意味がないことはわかっていますが、これ以上のものは見つかりませんでした。
次のようなキー/値/タイプの構成設定を保存できる SQlite テーブルへの C++ インターフェイスを提供する必要があります。
Key | Value | Type
PATH | /path/to/ | STRING
HAS_FEATURE | Y | BOOLEAN
REFRESH_RATE| 60 | INTEGER
単純さと柔軟性のために、データモデルは値を文字列としてホストしますが、元のデータ型を保持する列を提供します。
これは、クライアントがそのような c++ インターフェイスを呼び出す方法を想像した方法です。
Configuration c;
int refreshRate = c.get<int>("REFRESH_RATE");
// Next line throws since type won't match
std::string refreshRate = c.get<std::string>("REFRESH_RATE");
これは私がそれを実装することを想像した方法です(コードがそのままコンパイルされないことはわかっています。疑似C ++と考えてください。ここでの構文よりも設計に疑問があります)
class Parameter
{
public:
enum KnownTypes
{
STRING = 0,
BOOLEAN,
INTEGER,
DOUBLE,
...
}
std::string key;
std::string value;
KnownTypes type;
}
class Configuration
{
public:
template<class RETURNTYPE>
RETURNTYPE get(std::string& key)
{
// get parameter(eg. get cached value or from db...)
const Parameter& parameter = retrieveFromDbOrCache(key);
return <parameter.type, RETURNTYPE>getImpl(parameter);
}
private:
template<int ENUMTYPE, class RETURNTYPE>
RETURNTYPE getImpl(const Parameter& parameter)
{
throw "Tthe requested return type does not match with the actual parameter's type"; // shall never happen
}
template<Parameter::KnownTypes::STRING, std::string>
std::string getImpl(const Parameter& parameter)
{
return parameter.value;
}
template<Parameter::KnownTypes::BOOLEAN, bool>
std::string getImpl(const Parameter& parameter)
{
return parameter.value == "Y";
}
template<Parameter::KnownTypes::INTEGER, int>
int getImpl(const Parameter& parameter)
{
return lexical_cast<int>(parameter.value)
}
// and so on, specialize once per known type
};
それは良い実装ですか?それを改善する方法について何か提案はありますか?
get
publicを戻り値の型ごとに直接特殊化できることはわかっていますが、各テンプレートの特殊化 (型の一貫性チェックとパラメーターの取得) でいくつかのコードを複製することになります。