Я столкнулся с некоторыми проблемами при попытке сделать объявление друга с помощью проверок sfinae (вы можете просто перейти к примеру кода, если вам не нужны объяснения «почему» и «как»).
По сути, у меня есть некоторый шаблонный класс, объявляющий две закрытые функции-члена.В зависимости от реализации типа шаблона я хочу использовать одну или другую функцию.
Так что, если я не хочу, чтобы компиляция не удалась, закрытая функция, которую я не могу использовать, не может быть создана.Итак, я должен вызвать его через проверку sfinae (независимая функция).Учитывая, что это конфиденциально, я должен заставить свою sfinae проверить друга моего класса.
Однако я не могу этого сделать, как показывает следующий (минимальный) код.Вещи, которые я не хочу менять: прототип класса A (f1 и f2 должны оставаться закрытыми), прототипы классов B1 и B2.
Я понимаю, почему вещи в комментариях терпят неудачу (или я думаю,Да), но я не знаю, как это исправить.
#include <iostream>
template<class T> class A;
template<class T>
auto sfinae_check(T& t, A<T>& a, int) -> decltype(t.b1(), void());
template<class T>
auto sfinae_check(T& t, A<T>& a, long) -> decltype(t.b2(), void());
template<class T>
class A
{
void f1() { t.b1(); }
void f2() { t.b2(); }
T& t;
//friend auto sfinae_check<>(T &t, A<T> &a, int);//obviously mismatches everything
//friend auto sfinae_check<>(T &t, A<T> &a, int) -> decltype(t.b1(), void()); //failure : no member named b1
//friend auto sfinae_check<>(T &t, A<T> &a, long) -> decltype(t.b2(), void()); //failure : no member named b2
public:
A(T& t) : t(t) {}
void f() { sfinae_check(t, *this, 0); }
};
template<class T>
auto sfinae_check(T& t, A<T>& a, int) -> decltype(t.b1(), void())
{
a.f1();
}
template<class T>
auto sfinae_check(T& t, A<T>& a, long) -> decltype(t.b2(), void())
{
a.f2();
}
struct B1
{
void b1() { std::cout << "b1" << std::endl; }
};
struct B2
{
void b2() { std::cout << "b2" << std::endl; }
};
int main()
{
B1 b1; B2 b2;
A<B1> a1(b1);
a1.f(); //should print b1
A<B2> a2(b2);
a2.f(); //should print b2
}