I am writing some type traits to see if a free function exists with a specific set of parameters. Functions have a signature that looks something like this:
template <class T> void func( SomeClass &, SomeType const & );
I know the values ββfor T , SomeClass and SomeType . I want the property to return true if this function exists specifically with these parameters, without using any implicit conversion.
I can easily write some code to determine if this function exists using SFINAE to try to call it, for example.
// potentially in some namespace template <class> void func(); // this is necessary since user implementations // of func will not exist until after // this has been defined template <class X, class Y, class Z> static auto test(int) -> decltype( func<X>( std::declval<Y&>(), std::declval<Z const&>(), std::true_type()); template <class, class, class> static std::false_type test(...);
and by properly checking the return types of these functions. Since I pass SomeClass ( Y ) to the function here, ADL can allow the compiler to search in the appropriate namespaces so as not to get confused in the dummy version of func that I define for tests.
The problem I ran into is that since SomeType ( Z in the above test) is passed by a constant reference, it is allowed to implicitly convert other types. For example, someone can define a function such as: template <class T> void func( SomeClass &, double const & ); and for any arithmetic type for Z my test will pass. I would like this to be passed only when Z is a true type, in this case a double .
I tried to solve this problem using function pointers in a circuit similar to the following:
// struct to prevent implicit conversion and enforce function signature template <class Y, class Z> struct NoConvert { using FPType = void (*)(Y&, Z const &); explicit NoConvert( FPType ); }; template <class> void func(); // see note on why this is needed above template <class X, class Y, class Z> static auto test(int) -> decltype( NoConvert( &func<X> ), std::true_type() ); template <class, class, class> static std::false_type test(...); template <class X, class Y, class Z> static bool value(){ return std::is_same<decltype(test<X, Y, Z>()), std::true_type>::value; }
In theory, this will work fine, but the problem I am facing is that the later defined user version of func will not be tested by the test - it only sees the dummy func , which I need to determine for the compiler to be happy. Unfortunately, I cannot pass the SomeClass type here, so ADL cannot click to get &func<X> to search for later defined user-defined functions.
Is there any way to do this? There is no need to use function pointers in the solution, it just has to be a sign returning true if there is some free function with a precisely provided set of parameters.
For information on desired behavior:
template <class T> void func( A &, int const & ); value<T, A, int>(); // return true value<T, A, long>(); // return false value<T, A, double>(); // return false value<U, A, int>(); // return false value<T, B, int>(); // return false