When should I use std::any

后端 未结 4 1809
悲哀的现实
悲哀的现实 2020-12-16 12:39

Since C++17 std::any is introduced. One can now write code like this

#include 
#include 
#include 

int         


        
相关标签:
4条回答
  • 2020-12-16 12:58

    std::any is a vocabulary type. When you need to store, well, some bit of anything, as a value you can use it.

    There are a number of "first level" uses of it:

    1. When interacting with scripting languages which themselves have such types, it is a natural fit.

    2. When you have a property tree with highly polymorphic content, and the structure of the tree is decoupled from the producer and consumer of the tree.

    3. When replacing the equivalent of a void* chunk of data being passed through an intermediate layer who really doesn't care what it is carrying.

    It can also be used as a building block in other cases. For example, std::function could choose to store its value in the std::any:

    template<class R, class...Args>
    struct func<R(Args...)> {
      mutable std::any state;
      R(*f)(std::any& state, Args&&...) = nullptr;
      template<class T>
      void bind(T&& t) {
        state = std::forward<T>(t);
        f = [](std::any& state, Args&&...args)->R {
          return std::any_cast<T&>(state)(std::forward<Args>(args)...);
        };
      }
      R operator()(Args...args)const {
        return f(state, std::forward<Args>(args)...);
      }
    };
    

    that is a pretty small implementation of (most of) std::function. Basically I've used any to type erase copy/move/destroy.

    You can using this elsewhere for similar problems (where you are type-erasing some operation and also want to type erase copy/move/destroy), or generalize it.

    0 讨论(0)
  • 2020-12-16 13:00

    I would summarize it as classic "use when you cannot avoid it".

    I can only think of non-performance-critical implementations of dynamically typed scripting languages to represent variables from the scripting world, but even that with a stretch (Boost.Spirit/example/qi/compiler_tutorial does it without, for both the parser and the runtime).

    For everything else from parsers (e.g. Boost.Spirit.X3) to library APIs (e.g. ASIO) there would usually be a faster/better/more-specific alternative, as very few things are really "anything", most are more specific than that.

    • std::variant and/or std::optional for "almost any value"
    • std::packaged_task / std::function + lambdas for "callback with arguments", which would be a case of void* in C APIs.
    • etc.

    Specifically, I wouldn't blindly plug it as a replacement for a void*, as it may allocate memory on the heap, which can be deadly for high performance code.

    0 讨论(0)
  • 2020-12-16 13:01

    It's used in Wt, to provide a non-template interface for tabular data.

    There are conversions to string for builtin and Wt types, and you can register additional conversions by specialising Wt::any_traits. This allows anything to be displayed as an entry in a table, the view classes don't have to know anything about the types they are displaying.

    0 讨论(0)
  • 2020-12-16 13:15

    When to Use
    void* as an extremely unsafe pattern with some limited use cases, std::any adds type-safety, and that’s why it has some real use cases.

    Some possibilities:

    • In Libraries - when a library type has to hold or pass anything without knowing the set of available types.
    • Parsing files - if you really cannot specify what are the supported types.
    • Message passing.
    • Bindings with a scripting language.
    • Implementing an interpreter for a scripting language
    • User Interface - controls might hold anything
    • Entities in an editor
      (ref)
    0 讨论(0)
提交回复
热议问题