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 want a template function which takes a side
and a T
, and depending on the T
, returns a reference to "T.a
" or "T.b
" if the class has a member T::a
, or a reference to "T.a1
" or "T.b1
" if the class has a member T::a1
.
My starting point is:
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 get the compiler to skip the first template if the member a
does not exist.
So I implemented the solution given by @Jarod42 below, but it gave errors in VS 2015 because of a bug in VS ability to differentiate between templates. Here is a work around:
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 the comma operator and a special struct which represented each "concept"
Member functions can be function templates in several contexts. All functions of class templates are generic but aren't referred to as member templates or member function templates. If these member functions take their own template arguments, they're considered to be member function templates.
To instantiate a template function explicitly, follow the template keyword by a declaration (not definition) for the function, with the function identifier followed by the template arguments. template float twice<float>( float original ); Template arguments may be omitted when the compiler can infer them.
A non-template class can have template member functions, if required. Notice the syntax. Unlike a member function for a template class, a template member function is just like a free template function but scoped to its containing class.
Function Templates We write a generic function that can be used for different data types. Examples of function templates are sort(), max(), min(), printArray(). Know more about Generics in C++.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With