compile time selection of functions

I have following scenario:

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
31
32
33
34
35
36
37
38
39
40
#include <type_traits>

template<typename T>
struct A
{
};

template<typename T>
struct B
{
  void x()
  {
  }
};


struct C
{
      template<typename T>
      typename std::enable_if<std::is_member_function_pointer<decltype(&T::x)>::value>::type Process(T &b)
      {
        b.x();
      }
      template<typename T>
      typename std::enable_if<! std::is_member_function_pointer<decltype(&T::x)>::value>::type Process(T &a)
      {
      }
};

int main()
{
  A<int> a;
  B<int> b;
  C c;

  c.Process(a); // Error
  c.Process(b);

  return 0;
}



The function Process() does not exists for a. Is there a way depending on the paramter type or existance of the function x() that the compiler uses the one or the other function?
Last edited on
Hey, thank you

sorry for the late reply. It works like a charm. I'm not sure how tho...
I have a problem with it which I cannot really reproduce:

1
2
3
CREATE_MEMBER_CHECKS(GetInputName);
CREATE_MEMBER_CHECKS(IsInputNameEqual); // Error: "Member name specified in AmbiguitySeed is different from member name specified in Alias, or wrong Alias/AmbiguitySeed has been specified."
CREATE_MEMBER_CHECKS(GetOutputName);


How come? What could be the source of the problem?

Actually I renamed it to IsInputNameEqual1, but no avail
> I have a problem with it which I cannot really reproduce

Why can't you reproduce it?
Do you get this error with all compilers?


The static assertion failure is from here:
1
2
3
4
5
6
7
8
9
10
11
12
13
template<typename Alias, typename AmbiguitySeed>
struct has_member {
    template<typename C> static char ((&f(decltype(&C::value))))[1];
    template<typename C> static char ((&f(...)))[2];

    //Make sure the member name is consistently spelled the same.
    static_assert(
        (sizeof(f<AmbiguitySeed>(0)) == 1)
        , "Member name specified in AmbiguitySeed is different from member name specified in Alias, or wrong Alias/AmbiguitySeed has been specified."
    );

    static bool const value = sizeof(f<Alias>(0)) == 2;
};

Make sure that no inadvertent modification has crept into your copy of Brett Rossier's code.
Why can't you reproduce it?
Do you get this error with all compilers?
My main compiler environment is Visual Strudion 2015. To test the issue I have a separate project with another environment: GCC/Code Blocks.

In VS the error occurs, for GCC it doesn't.

From what I've tested the problem is the second macro for a second member function of the same class. The name of the member seems to be irrelevant.

I can't tell what that sizeof(...) on line 8 evaluates, but it is obviously not 1 for the second case.

Make sure that no inadvertent modification has crept into your copy of Brett Rossier's code.
Yes, I copied the whole code including the surrounding comments.
Consider using boost TTI.

In general, consider using boost.
More widely used, tested with a variety of compilers, work arounds for popular compilers etc.

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
31
32
//Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23506 for x86

#include <iostream>
#include <boost/tti/has_member_function.hpp>

BOOST_TTI_HAS_MEMBER_FUNCTION(first_member)
BOOST_TTI_HAS_MEMBER_FUNCTION(second_member)
BOOST_TTI_HAS_MEMBER_FUNCTION(third_member)
    

struct A
{
    virtual int first_member( char, short, int, long, ... ) noexcept ;
    virtual bool second_member() const noexcept ;
    A* first_member(int) ;
    const A* first_member(int) const ;
};

int main()
{
    std::cout << std::boolalpha
              << has_member_function_first_member< int (A::*)(char,short,int,long,...) >::value << '\n' // true
              << has_member_function_second_member< bool (A::*)() const >::value << '\n' // true
              << has_member_function_first_member< A* (A::*)(int) >::value << '\n' // true
              << has_member_function_first_member< const A* (A::*)(int) const >::value << '\n' // true
        
              << has_member_function_second_member< A* (A::*)(int) >::value << '\n' // false
              << has_member_function_second_member< void (A::*)() const >::value << '\n' // false
              << has_member_function_first_member< A* (A::*)(int) const >::value << '\n' // false
              << has_member_function_third_member< A* (A::*)(int) >::value << '\n' ; // false
        
}

http://rextester.com/VMY26520
Consider using boost TTI.
Yes, I always do, but actually I failed to see that boost offers this...

And it works, thank you.
Topic archived. No new replies allowed.