Select a member-based template function

Let's say you have these two classes:

class A { public: int a; int b; } class B { public: int a; int b; } class C { public: float a1; float b1; } enum class Side { A, B }; 

I need a template function that takes side and T , and depending on T returns a link to " Ta " or " Tb " if the class has a member T::a or a link to " T.a1 " or " T.b1 ", if the class has a member T::a1 .

My starting point:

 template<typename T> auto &GetBySide(const Side &side, const T &twoSided) { return side == Side::A?twoSided.a:twoSided.b; } template<typename T> auto &GetBySide(const Side &side, const T &twoSided) { return side == Side::A?twoSided.a1:twoSided.b1; } 

The question is how to make the compiler skip the first template if member a does not exist.

So, I implemented the solution given by @ Jarod42 below, but it gave errors in VS 2015 due to an error in VS's ability to distinguish between templates. Here is the work:

 template<typename T> auto GetBySide(const Side &side, const T& twoSided) -> decltype((twoSided.a)) { return side == Side::A ? twoSided.a : twoSided.b; } // Using comma operator to trick compiler so it doesn't think that this is the same as above template<typename T> auto GetBySide(const Side &side, const T &twoSided) -> decltype((0, twoSided.a1)) { return side == Side::A ? twoSided.a1 : twoSided.b1; } // See comment above template<typename T> auto GetBySide(const Side &side, const T &twoSided) -> decltype((0, 0, twoSided.a2)) { return side == Side::A ? twoSided.a2 : twoSided.b2; } 

Another way would be to use a comma operator and a special structure that would represent each β€œconcept”

+6
source share
1 answer

With SFINAE.

 template<typename T> auto GetBySide(const Side &side, const T& twoSided) -> decltype((twoSided.a)) { return side == Side::A ? twoSided.a : twoSided.b; } template<typename T> auto GetBySide(const Side &side, const T &twoSided) -> decltype((twoSided.a1)) { return side == Side::A ? twoSided.a1 : twoSided.b1; } 

Demo

+11
source

Source: https://habr.com/ru/post/1014340/


All Articles