简体   繁体   中英

Use std::map with std::any as value type

I'd like to have class Config able to store literally any value within a string key. For that purpose it seems that std::map fits. Unfortunately this isn't compiling.

That looks like that std::is_copy_constructible<std::tuple<const std::any&>> trait fails. How can I overcome that? Please find source at https://github.com/marchevskys/VisualEngine .

The code idea the same as follows,

#include <iostream>
#include <string>
#include <vector>
#include <functional>
#include <any>
#include <map>
//#include <glm/glm.hpp>

//using vec3d = glm::vec<3, double, glm::highp>;

class Config {
public:
   static Config* get() {
    static Config config;
    return &config;
    }

   enum class Option : int {
      ImGuiEnabled = 0x0,   // bool
      ShipPosition = 0x1    // glm::vec3
   };

   using cb_function = std::function<void(std::any)>;

   bool is_option_available(Option option) const { return m_config.at(option).has_value(); }
   std::any get_option(Option option) const { return m_config.at(option); }
   void set_option_value(Option option, const std::any& value) { m_config.insert_or_assign(option, value); }
private:
   Config() {/* m_config[Option::ShipPosition] = vec3d({ 0., 0., 0. }); */} 
   ~Config() = default;
   std::map<Option, std::any> m_config;
};

int main()
{
    Config::get()->set_option_value(Config::Option::ImGuiEnabled, false);
    bool isImGuiEnabled = std::any_cast<bool>(Config::get()->get_option(Config::Option::ImGuiEnabled));
    std::cout << std::boolalpha << "ImGuiEnabled ? " << isImGuiEnabled << std::endl;
}

That compiled on MS Visual Studio, and with older than 9.1.0 g++, but won't compile on g++ 9.1.0.

You can get the same error with:

#include <type_traits>
#include <tuple>
#include <any>

int main()
{
  bool b = std::is_copy_constructible< std::tuple<const std::any&> >::value );
  (void)b;
}

The strange error is triggered when we ask "can a std::tuple<const std::any&> be copied".

This ends up breaking, because it being copied ends up checking "can std::tuple<const std::any&> be copied" as an intermediate step.

This is because one of the intermediate steps involves checking if you can make a std::any const& from a std::tuple<std::any const&> , which in turn asks if you can copy a std::tuple<std::any const&> , which asks if you can make a std::any const& from a std::tuple<std::any const&> , etc.

All of this seems to be triggered by code in the map that bundles the 2nd argument up in a std::tuple , then tries to emplace-construct the std::any with it. But it tries both constructing the std::any with the arguments and with the tuple as a whole.

This seems to be a mistake in the GCC standard library.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM