[英]C++ - return different variable types
我不知道這是否可能,但也許還有其他解決方案可以滿足我的需求。 我正在嘗試從設置文件中獲取設置。 它們可以是字符串(如名稱),整數或布爾值。 當然,它們作為文本存儲在文件中,但我將創建一個用於打開和返回設置的類,但不是作為字符串,而是實際上每個都是什么。
class Settings {
public:
Settings(string FileName);
template <class T> T Setting(string SettingName);
}
例如,構造函數將加載文件,將解析設置並將它們存儲為映射。 現在,當我調用設置成員函數時,我希望它確定所請求設置的值是什么類型(如果是數字,則為整數,如果為“true”或“false”為布爾值,如果是字母數字字符串)並返回該類型的值。 一個例子
Settings UserPreferences("Preferences.cfg");
bool AutoLogin = UserPreferences.Setting("autologin"); // return bool
string UserName = UserPreferences.Setting("username"); // return string or char*
我查看了模板,但看起來我必須在創建Settings對象時指定我期望的變量,但這不是重點。 我很高興聲明要返回的變量類型如下:
bool AutoLogin = UserPreferences.Setting<bool>("autologin");
string UserName = UserPreferences.Setting<string>("username");
但我不知道這是否可能。 你怎么看?
這絕對是可能的,盡管您必須保證它可以轉換為給定類型。 在XNA的ContentLoader中可以看到很多(盡管系統差別很大)。 您可以使用此方法來簡化和抽象檢索事物的存儲方式。 考慮:
class Loader
{
private:
vector<void*> _items;
public:
template <typename Type>
Type GetItem( int index ) { return (Type)(_items[ index ]); }
};
我們的想法是,只要您可以可靠地(比示例更可靠)將內部數據轉換為所請求的類型,而不是完全合法的操作。 如何使保證成功完全是另一個問題,但你肯定可以有返回類型為其模板類型的方法。 考慮以下示例(我使用的是資源加載器的大學項目):
Header.h
class BasicResource
{
public:
static const int ResourceID;
const int ID;
BasicResource( )
: ID( ResourceID )
{
}
};
class Loader
{
private:
vector<BasicResource*> _items;
public:
template <typename Type>
Type GetItem( int index );
};
#include "inline.inl"
Inline.inl
template <typename Type>
Type Loader::GetItem( int index )
{
auto item = _items[ index ];
if( item != nullptr && item->ID == Type::ResourceID )
{
return (Type)_item;
}
else
{
// Handle the fail case somehow
}
}
內聯文件允許您像往常一樣分離邏輯,但將其包含在允許導出模板方法的標題中。
是的,這肯定是可能的。 我寫了以下一些完整的代碼來證明這一點:
#include <iostream>
#include <map>
#include <string>
#include <sstream>
#include <stdexcept>
struct Settings
{
typedef std::map<std::string, std::string> SettingsMap;
template <class T> T as( const std::string& name ) const
{
std::istringstream is( getEntry( name ) );
T value;
if( is )
{
if( (is >> value) || (is.eof() && !is.fail()) )
{
return value;
}
}
//Exception handling not in scope of question
throw std::runtime_error( "..." );
};
const std::string& getEntry( const std::string& name ) const
{
SettingsMap::const_iterator pos( settingsMap_.find( name ) );
if( pos != settingsMap_.end() )
{
return pos->second;
}
//Not part of the scope of this answer....
throw std::invalid_argument( "No such setting..." );
}
Settings()
{
settingsMap_["mybool"] = "1";
settingsMap_["myint"] = "5";
settingsMap_["myfloat"] = "43.2";
}
SettingsMap settingsMap_;
};
int main()
{
Settings s;
std::cout << s.as<bool>("mybool") << " "
<< s.as<int>("myint") << " "
<< s.as<float>("myfloat");
return 0;
}
我已經實現了與此類似的東西,但我使用了boost :: any作為我的映射類型,並且我在第一次解析時讀取了實際類型,因此確保存儲的類型是正確的。 我也使用了boost :: lexical_cast而不是native istringstream,但為了證明這一點,我省略了它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.