template class B;
template class A
{
public:
friend class B;
operator B ();
};
template class B
{
public:
B operator * (const B &s2) const {}
friend class A;
A operator [] (const B &s2) {}
};
template A::operator B ()
{
return B();
}
int main()
{
B s1,s2,s3;
s1[s2]*s3; // <-- ошибка
}
[Error] no match for 'operator*' (operand types are 'A' and
'B')
Почему не работает оператор приведения?
UPD
Оказывается, вот это компилится
#include
template class B;
template std::ostream& operator << (std::ostream &os, const B &s)
{
}
template class A
{
public:
friend class B;
operator B();
};
template class B
{
public:
friend class A;
A operator [] (const B &s2) {}
friend std::ostream& operator << (std::ostream &, const B &);
};
template
B operator*(const A& s1, const B& s2)
{
return B();
}
template A::operator B()
{
return B();
}
int main()
{
B s1, s2, s3;
std::cout << s1[s2] * s3;
}
Так что, возможно, проблема с другим связана
Ответ
Вся проблема заключается в ADL (Argument Dependent Lookup), если же вы operator* реализуете отдельно от класса, то проблема будет решена:
template class B;
template class A
{
public:
friend class B;
operator B();
};
template class B
{
public:
friend class A;
A operator [] (const B &s2) { return A(); }
};
template
B operator*(const A& s1, const B& s2){ return B(); }
template A::operator B(){ return B(); }
int main()
{
B s1, s2, s3;
s1[s2] * s3;
}
Пояснение
Операторы, определенные в теле класса, не видны извне класса и могут быть найдены только при помощи ADL (поиска по типам аргументов).
Оператор приведения типа тут просто не успевает сработать, т.к. компилятор даже не знает что экземпляр класса A необходимо привести к классу B (да и вообще, какому-либо классу), а реализация данного оператора находится именно внутри класса B
Комментариев нет:
Отправить комментарий