C++ I';我在运算符[]中使用了一个代理来隐式转换boost::variant。如何通过操作员[]维护作业?

C++ I';我在运算符[]中使用了一个代理来隐式转换boost::variant。如何通过操作员[]维护作业?,c++,stl,operator-overloading,C++,Stl,Operator Overloading,我正在编写一个配置文件解析器,它将格式为key:value的配置文件读入std::mapProxy当前存储映射中的ConfigVariant副本。相反,让它在地图中存储指向原始对象的引用或指针。然后,您可以实现Proxy::operator=以重新分配给该值。您实际上并不“推断变量的类型”。您刚刚完成了从variant到目标变量类型的完全隐式转换 我根本不建议这样做,如果不使用variant来增加“自动做错事”的风险,隐式转换就已经够糟糕的了 这就是说,由于转换只在假设变量包含您首先要转换到的确

我正在编写一个配置文件解析器,它将格式为
key:value
的配置文件读入
std::map
Proxy
当前存储映射中的
ConfigVariant
副本。相反,让它在地图中存储指向原始对象的引用或指针。然后,您可以实现
Proxy::operator=
以重新分配给该值。

您实际上并不“推断变量的类型”。您刚刚完成了从variant到目标变量类型的完全隐式转换

我根本不建议这样做,如果不使用variant来增加“自动做错事”的风险,隐式转换就已经够糟糕的了

这就是说,由于转换只在假设变量包含您首先要转换到的确切类型的情况下起作用,因此您可以同样轻松地返回一个引用:

typedef boost::variant<double, long int, std::string> ConfigVariant;

class Config {
private:
  std::map<std::string, ConfigVariant> config_values;

  // This struct is important
  struct Proxy {
  public:
    template<typename T> T& as() { return boost::get<T>(data); }
    template<typename T> operator T&() { return as<T>(); }

  private:
    ConfigVariant& data;

    Proxy(ConfigVariant& data) { this->data = data; }
    Proxy(const Proxy &other);
    Proxy & operator=(const Proxy &other);
    friend class Config;
  };

public:
  Config(std::string config_file_name);
  Proxy operator[] (const std::string &key); // Important
};

重载代理上的赋值运算符,就像对转换运算符所做的那样。我建议使用Boost PropertyTree、JsonCPP或类似方法。谢谢您的建议。这个配置解析器实际上只是我为了好玩而做的一个项目,因此使用这些库将无法达到全部目的;)我尝试了
Proxy&operator=(ConfigVariant&other)
ConfigVariant&operator=(ConfigVariant&other)
。请参阅我的编辑以了解这些错误。have
operator=
take
const-ConfigVariant&
。非常量引用不能绑定到临时引用。隐式转换当然很危险,但至少可以使用
app\u config[key].as()
来显式转换。至于您的解决方案,它很有趣,但我无法将其编译。另外,我正在寻找像
app\u config[key]=new\u value
这样的东西,这是目前不起作用的东西。
Config::Proxy Config::operator[] (const string &key) {
  return Proxy(config_values[key]);
}
// config_file
double_key: 4.2

// driver.cpp
int main() {
  Config config("path/to/config_file");

  double d = config["double_key"] // Look ma, no cast
  d += 1

  cout << d << endl; // Prints 5.2

  return 0;
}
Proxy & operator=(ConfigVariant &other) { *data = other; return *this; }
app/driver.cpp: In function ‘int main()’:
app/driver.cpp:11: error: no match for ‘operator=’ in ‘Config::operator[](const std::string&)(((const std::string&)(& std::basic_string<char, std::char_traits<char>, std::allocator<char> >(((const char*)"key3"), ((const std::allocator<char>&)((const std::allocator<char>*)(& std::allocator<char>()))))))) = 5.20000000000000017763568394002504646778106689453125e+0’
app/../config/config.hpp:37: note: candidates are: Config::Proxy& Config::Proxy::operator=(const Config::Proxy&)
app/../config/config.hpp:44: note:                 Config::Proxy& Config::Proxy::operator=(ConfigVariant&)
ConfigVariant & operator=(ConfigVariant &other) { *data = other; return *data; }
app/driver.cpp: In function ‘int main()’:
app/driver.cpp:11: error: no match for ‘operator=’ in ‘Config::operator[](const std::string&)(((const std::string&)(& std::basic_string<char, std::char_traits<char>, std::allocator<char> >(((const char*)"key3"), ((const std::allocator<char>&)((const std::allocator<char>*)(& std::allocator<char>()))))))) = 5.20000000000000017763568394002504646778106689453125e+0’
app/../config/config.hpp:37: note: candidates are: Config::Proxy& Config::Proxy::operator=(const Config::Proxy&)
app/../config/config.hpp:44: note:                 ConfigVariant& Config::Proxy::operator=(ConfigVariant&)
typedef boost::variant<double, long int, std::string> ConfigVariant;

class Config {
private:
  std::map<std::string, ConfigVariant> config_values;

  // This struct is important
  struct Proxy {
  public:
    template<typename T> T& as() { return boost::get<T>(data); }
    template<typename T> operator T&() { return as<T>(); }

  private:
    ConfigVariant& data;

    Proxy(ConfigVariant& data) { this->data = data; }
    Proxy(const Proxy &other);
    Proxy & operator=(const Proxy &other);
    friend class Config;
  };

public:
  Config(std::string config_file_name);
  Proxy operator[] (const std::string &key); // Important
};
// driver.cpp
Config config("path/to/config_file");

double& d = config["double_key"] // Look ma, no cast
d += 1;                          // edits the Config instance