How to have template type deduced in std::function arguments with lambda?

前端 未结 1 2013
余生分开走
余生分开走 2020-12-11 07:50

I have a boost::variant and I would like to execute a functor only if the variant is of a special type, so I made up this function:

template

        
相关标签:
1条回答
  • 2020-12-11 08:36

    I recommend you think of std::function<Sig> as a container of any one functor that conforms to Sig as a signature -- and which can be replaced at any moment. This functionality comes in very handy for e.g. std::vector<std::function<Sig>> because such a container can then hold functors of different types.

    In your case, because you only care to have just the one functor you really don't need the functionality of std::function<Sig>. As such, I recommend you declare your function template like so:

    template<typename T, typename Variant, typename Functor>
    void if_init(Variant& opt_variant, Functor functor);
    

    If you are worried that this doesn't communicate that Functor must conform to a void(T) signature, please note that std::function<Sig> does not enforce that either: although obviously you will end up with a compilation error, it is not a nice one. It's planned to be changed (and maybe your implementation has that either), but changed to a different kind of error. Still not that helpful for your case.

    I personally make use of template aliases (in the template parameter list) to both document and enforce what a functor should conform to. This ends up looking like:

    // Documents that e.g. long l = std::forward<Functor>(functor)(42.)
    // should be a valid expression -- a functor that returns int would
    // also be accepted.
    // Triggers a hard-error (typically a static_assert with a nice message)
    // on violation.
    template<typename Functor, Requires<is_callable<Functor, long(double)>>...>
    R foo(Functor functor);
    
    // Documents that this function template only participates in overload resolution
    // if the functor conforms to the signature.
    // Does not trigger a hard-error (necessary by design); if everything goes right
    // then another overload should be picked up -- otherwise an error of the kind
    // 'no matching overload found' is produced
    template<typename Functor, EnableIf<is_callable<Functor, long(double)>>...>
    R bar(Functor functor);
    

    As to your exact question, the rules of C++ do not allow for a template parameter to be deduced in your case. It's really not an easily fixed 'problem', if it is one. You can find more information on this.

    0 讨论(0)
提交回复
热议问题