Powiedzmy masz te dwie klasy:Wybierz funkcję szablonu na podstawie istnienia członka
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 };
chcę funkcję szablonu, który pobiera side
i T
, oraz w zależności od T
, zwraca odwołanie do " T.a
"lub" T.b
", jeśli klasa ma członka T::a
, lub odniesienie do" T.a1
"lub" T.b1
", jeśli klasa ma członka T::a1
.
Moim punktem wyjścia jest:
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;
}
Chodzi o to, jak dostać kompilator pominąć pierwszy szablon jeśli członek a
nie istnieje.
Więc zaimplementowałem rozwiązanie podane przez @ Jarod42 poniżej, ale dało błędy w VS 2015 z powodu błędu w umiejętności VS do rozróżniania szablonów. Tutaj znajduje się obejść:
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;
}
Innym sposobem byłoby użyć operatora przecinek oraz specjalny struct których każdy reprezentowany „pojęcie”
To jeden ze sposobów, które próbowałem, ale ja już otrzymuję błąd z Visual Studio stwierdzające, że szablon funkcja została już zdefiniowana. – bpeikes
@ Jarod42 Dzień, w którym zdajesz sobie sprawę, że 'auto f() -> decltype ((wyrażenie)) zwraca referencję (i mówisz - że to oczywiste, jak to się stało, że nigdy wcześniej o tym nie myślałem?) . Dobry połów. +1 – skypjack
@skypjack - w rzeczywistości nie zwraca referencji. Upadłem w tę dziurę. Aby zwrócić referencję, potrzebujesz: auto f() -> decltype (wyrażenie) i – bpeikes