SFINAE problem

Hello,

I'm trying to use SFINAE to detect when a class has a member function but I have found a problem when the class has two member functions with the same name. Is there a way to solve it?

Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <cstdio>

template <typename T>
class HasGetPtr
{
private:
    typedef char YesType[1];
    typedef char NoType[2];

    template <typename C> static YesType & test( decltype(&C::GetPtr) ) ;
    template <typename C> static NoType  & test(...);
public:
    enum { value = sizeof(test<T>(0)) == sizeof(YesType) };
};

struct Foo {
    const float *GetPtr() const { return 0;}
    float *GetPtr() { return 0;}
};

int
main(int argc, char *argv[]) {

    if (HasGetPtr<Foo>::value)
        printf("yes");
    else
        printf("no");

    return 0;
}


If you comment one of the two functions in the Foo class, the program prints "yes" but with both functions the program prints "no".
I'm puzzled with this.
Last edited on
> If you comment one of the two functions in the Foo class, the program prints "yes"
> but with both functions the program prints "no".
> I'm puzzled with this.

With both the functions present, &foo::GetPtr (address of overloaded function) can't be resolved; http://coliru.stacked-crooked.com/a/aa8da01f5ce5a87a
so there is a substitution failure.

We can use boost TTI https://www.boost.org/doc/libs/1_72_0/libs/tti/doc/html/the_type_traits_introspection_library/tti_detail_has_member_function.html

For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <boost/tti/has_member_function.hpp>

BOOST_TTI_HAS_MEMBER_FUNCTION(GetPtr)

struct Foo {

    const float *GetPtr() const { return 0;}
    float *GetPtr() { return 0;}
};

int main() {

    std::cout << std::boolalpha
              << has_member_function_GetPtr< const float* (Foo::*)() const >::value << '\n' // true
              << has_member_function_GetPtr< float* (Foo::*)() >::value << '\n' ; // true

}

http://coliru.stacked-crooked.com/a/4aab130cb863856a
Do you know any solution without using boost or other external library? (just the standard)
1
2
3
4
5
6
7
8
template <typename C> 
  static constexpr std::true_type test
    (decltype(std::declval<C>().GetPtr())*) noexcept;
template <typename C>
  static constexpr std::false_type test(...) noexcept;

template <typename C>
inline constexpr decltype(test<C>(nullptr)) has_GetPtr {}; 

http://coliru.stacked-crooked.com/a/cf4f91b7159a1abb
Last edited on
Topic archived. No new replies allowed.