簡體   English   中英

C ++ - 返回不同的變量類型

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM