C++ detecting free function existence with explicit parameters

后端 未结 1 1464
别跟我提以往
别跟我提以往 2020-12-16 23:05

I\'m writing some type traits to see if a free function exists with a specific set of parameters. The functions have a signature that looks something like this:

<         


        
相关标签:
1条回答
  • 2020-12-16 23:43

    I was able to solve this using the following technique, thanks to help from dyp:

    This solution no longer makes use of function pointers and instead relies on a proxy class that prevents implicit conversion:

    template <class Source>
    struct NoConvert
    {
      template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
      operator Dest () const = delete;
    
      template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
      operator Dest const & () const;
    };
    
    template <class> void func();
    
    template <class A, class T, class U>
    static auto test(int) -> decltype( func<A>( std::declval<T&>(), NoConvert<U>() ), std::true_type() );
    
    template <class, class, class>
    static std::false_type test(...);
    
    template <class A, class T, class U>
    static bool valid()
    {
      return std::is_same<decltype(test<A, T, U>(0)), std::true_type>::value;
    }
    

    which can be used like:

    template <class T>
    void func( B &, int const & );
    
    template <class T>
    void func( B &, std::string );
    
    template <class T>
    void func( A &, std::string const & );
    
    std::cout << valid<A, B, int>() << std::endl;         // true
    std::cout << valid<A, B, std::string>() << std::endl; // false
    std::cout << valid<A, A, std::string>() << std::endl; // true
    

    By playing with the conversion operators inside of NoConvert, you can make this work with passing by value, reference, or constant reference.

    For example, in the current use, when the conversion operator for NoConvert<std::string> is triggered by a value parameter of std::string, both overloads are valid and thus there is ambiguity, meaning that SFINAE will cull this and allow the std::false_type test to pass. In the case of a constant reference parameter, the constant reference overload has precedence and properly allows the std::true_type test overload to pass.

    This solution also relies on the ability to use ADL to resolve the name of the function, which was impossible with the function pointer approach.

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