Checking for existence of an (overloaded) member function

前端 未结 2 348
后悔当初
后悔当初 2021-01-03 07:48

There are a number of answered questions about checking whether a member function exists: for example, Is it possible to write a template to check for a function's exis

2条回答
  •  一向
    一向 (楼主)
    2021-01-03 08:14

    // use std::void_t in C++... 17 I think? ... instead of this:
    templatestruct void_type { using type = void; };
    templateusing void_t = typename void_type::type;
    
    template
    using hello_world_ify = decltype(
          std::declval().helloworld( std::declval()... )
    );
    
    template
    struct has_helloworld:std::false_type{};
    
    template
    struct has_helloworld
      >
    >:std::true_type{};
    
    template
    struct has_helloworld::value &&
        std::is_convertible<
          hello_world_ify,
          R
        >::value
      >::type
    >:std::true_type{};
    

    live example

    I'd put the above in a details namespace, and then expose a template struct has_helloworld:details::has_helloworld{}; so someone doesn't pass a type in place of the defaulted void.

    We use SFINAE to detect if we can invoke T.helloworld(Args...). If the passed in signature is void(blah), we just detect if the call can occur -- if not, we test that the return type of T.helloworld(Args...) can be converted into the return type of the signature.

    MSVC has significant issues doing SFINAE with decltype, so the above may not work in MSVC.

    Note that has_helloworld corresponds to passing in an rvalue T, invoking helloworld in that rvalue context passing it rvalue Args.... To make the values lvalues, add &. To make them const lvalues, use const& on the types. However, this should mostly only matter in some corner cases.

    For the more general case, there is no way to detect the existence of an overridden method without having a sample signature to match.

    The above can be adapted to handle exact signature matches.

    Amusingly, if there is a signature conflict (ie, an error would occur in the immediate context of the call), it acts as if there is no such method.

    As it relies on SFINAE, errors in the non-immediate context do not trigger failure.

提交回复
热议问题