#include <iostream>
using namespace std;
template<int size>
class A
{
};
template<int size>
A<size> operator&(const A<size>&, const A<size>&);
enum class En : int { a, b, c };
int main() {
En en1 = En::a;
En en2 = En::b;
En en3 = En::a & En::b;
return 0;
}
VS2013 ругается: <source>(19): error C2784: 'A<size> operator &(const A<size> &,const A<size> &)': could not deduce template argument for 'const A<size> &' from 'En'
<source>(11): note: see declaration of 'operator &'
<source>(19): error C2676: binary '&': 'En' does not define this operator or a conversion to a type acceptable to the predefined operator
Хочется спросить у знатоков С++ — что происходит с перегрузкой, почему так и по стандарту ли это? Можно как-то поправить (сделать что бы operator& разрешался только для класса A<uint_t>) ?
Здравствуйте, Videoman, Вы писали:
V>Хочется спросить у знатоков С++ — что происходит с перегрузкой, почему так и по стандарту ли это? Можно как-то поправить (сделать что бы operator& разрешался только для класса A<uint_t>) ?
В примере вообще operator& описан для класса A<size>, а применяется на enum'ах, причём класса En. Ругается, что не может enum преобразовать в A
M>>Перенести его декларацию внутрь класса. V>На самом деле такой оператор у "боевого" класса есть. С ним нет проблем. Интересует именно как решить перегрузку свободного operator&.
Тогда зачем тебе нужно чтобы внешний оператор& выполнялся для класса A, если у этого класса есть внутренний оператор& ?
Здравствуйте, Maniacal, Вы писали:
M>В примере вообще operator& описан для класса A<size>, а применяется на enum'ах, причём класса En. Ругается, что не может enum преобразовать в A
Здравствуйте, Muxa, Вы писали:
M>Тогда зачем тебе нужно чтобы внешний оператор& выполнялся для класса A, если у этого класса есть внутренний оператор& ?
V>Т.е. это такое завуалированное сообщение о том что не найден оператор для En ? Если у меня будет еще куча перегрузок, то он их все выведет?
Ну clang говорит
prog.cc:19:20: error: invalid operands to binary expression ('En' and 'En')
En en3 = En::a & En::b;
~~~~~ ^ ~~~~~
/opt/wandbox/clang-head/include/c++/v1/bitset:1061:1: note: candidate template ignored: could not match 'bitset<_Size>' against 'En'
operator&(const bitset<_Size>& __x, const bitset<_Size>& __y) _NOEXCEPT
^
prog.cc:11:9: note: candidate template ignored: could not match 'A<size>' against 'En'
A<size> operator&(const A<size>&, const A<size>&);
^
1 error generated.
Разница с VC как я понимаю только в том, что VC генерирует по ошибке на кандидата, а clang перечисляет их в note к одной ошибке.
Здравствуйте, Videoman, Вы писали:
V>Здравствуйте, Maniacal, Вы писали:
M>>В примере вообще operator& описан для класса A<size>, а применяется на enum'ах, причём класса En. Ругается, что не может enum преобразовать в A
V>Так в этом и вопрос, почему?
У это нужно спросить у автора этих строк, зачем он так написал.
Не понятно, что тебя удивляет. Оператор & для класс-перечислений не определен, шаблонный оператор тоже не подходит — вот компилятор и жалуется. А ты чего бы хотел?
Здравствуйте, Vamp, Вы писали:
V>Не понятно, что тебя удивляет. Оператор & для класс-перечислений не определен, шаблонный оператор тоже не подходит — вот компилятор и жалуется. А ты чего бы хотел?
Ох. Трудно привести полностью не рабочий пример.
На самом деле у меня для Enum-а тоже есть опретор & но он хитро определен, примерно так:
namespace impl
{
En operator&(const En&, const En&);
}
using impl;
В тестовых примерах у меня сейчас все компилируется, а вот в рабочем коде у меня постоянное срабатывает перегрузка оператора & для A<size> при использовании Enum-а, хотя должно разрешаться с помощью ADL.
во — воспроизвел пример
Здравствуйте, Videoman, Вы писали:
V>Здравствуйте, Vamp, Вы писали:
V>>Не понятно, что тебя удивляет. Оператор & для класс-перечислений не определен, шаблонный оператор тоже не подходит — вот компилятор и жалуется. А ты чего бы хотел?
V>Ох. Трудно привести полностью не рабочий пример. V>На самом деле у меня для Enum-а тоже есть опретор & но он хитро определен, примерно так: V>
V>В тестовых примерах у меня сейчас все компилируется, а вот в рабочем коде у меня постоянное срабатывает перегрузка оператора & для A<size> при использовании Enum-а, хотя должно разрешаться с помощью ADL. V>во — воспроизвел пример
А вот если убрать перегрузку для A<size>, то все начинает работать как нужно.
Здравствуйте, Muxa, Вы писали:
M>Вот еще пара рабочих примеров: M>https://gcc.godbolt.org/z/6UGypb M>https://gcc.godbolt.org/z/np-RS4
M>Выбирай который больше нравится и подходит M>Похоже компилятор не может найти оператор объявленный в соседнем нэймспайсе, даже если ты делаешь юзинг.
Спасибо конечно, но у меня проблема посложнее чем просто заставит код компилироваться. Хотелось бы понять что делать с этим и почему ADL сбоит
V>В тестовых примерах у меня сейчас все компилируется, а вот в рабочем коде у меня постоянное срабатывает перегрузка оператора & для A<size> при использовании Enum-а, хотя должно разрешаться с помощью ADL. V>во — воспроизвел пример
Во-первых, ADL тут вообще не причем. Чтобы было ADL, твоя функция должна жить в том же пространстве имен, что и тип. А у тебя ничего такого и в помине нет — тип живет в глобальном пространстве, функция в impl.
Во-вторых, ты, как мне кажется, не вполне понимаешь механизм работы using-директивы. В твоем случае, она работает как если бы твой оператор & для перечислений находился в глобальном пространстве имен.
В-третьих, в результате всего этого имеем горький катаклизм — в глобальном пространстве имен имеется подходящий оператор &, но в локальном пространстве имен (my) тоже имеется оператор &, и как только компилятор его находит, поиск прекращается. Вариантов исправления на самом деле много, зависит от того, что в конечном итоге тебе надо.
Простейший вариант — вместо using namespace impl делать using impl::operator&. Но в рабочем коде я не уверен, что это то, что тебе надо.
Здравствуйте, Vamp, Вы писали:
V>Во-первых, ADL тут вообще не причем. Чтобы было ADL, твоя функция должна жить в том же пространстве имен, что и тип. А у тебя ничего такого и в помине нет — тип живет в глобальном пространстве, функция в impl.
Хорошо, хорошо. Вот более полный пример. Идея была в том, что бы для строгих enum-ов автоматически определять битовые операции если надо с помощью декларации void enable_bitmask_operators(Enum);. А вот если раскомментарить A<size> operator&(const A<size>&, const A<size>&); то все перестает работать.
V>Во-вторых, ты, как мне кажется, не вполне понимаешь механизм работы using-директивы. В твоем случае, она работает как если бы твой оператор & для перечислений находился в глобальном пространстве имен.
Возможно что и так. Я всегда думал что using внутри namespace затаскивает указанный namespace туда
V>В-третьих, в результате всего этого имеем горький катаклизм — в глобальном пространстве имен имеется подходящий оператор &, но в локальном пространстве имен (my) тоже имеется оператор &, и как только компилятор его находит, поиск прекращается. Вариантов исправления на самом деле много, зависит от того, что в конечном итоге тебе надо.
У меня в реале функция шаблонная и я пока не пойму как это сделать правильно.