2016-12-17 2 views
2

По крайней мере, с унарным & и унарным - появляется GCC позволит вам удалить как неконстантную, так и константную версию оператора или none (это, вероятно, влияет на двоичные операторы, но я не проверял). Как описано в комментариях ниже, хотя я могу успешно перегружать на основе const, я не могу индивидуально удалять перегрузку const или non-const без использования компиляции. Является ли это поведение стандартным? Это кажется противоречивым.Не удается удалить только константную перегрузку метода?

Протестировано с помощью GCC 5.4.0.

#include <iostream> 

struct A { 
    // These both being defined at the same time is fine, 
    // and whether or not x is const as expected will change 
    // which overload you get. 

    A* operator&() { 
     std::cout << "hello" << std::endl; 
     return this; 
    } 

    const A* operator&() const { 
     std::cout << "world" << std::endl; 
     return this; 
    } 



    // assuming both definitions above are commented out, 
    // regardless of whether or not x is const 
    // either one of these lines being present 
    // will make the example not compile! 

    // A* operator&() = delete; 
    // const A* operator&() const = delete; 



    // Finally if you have the const version defined and the non-const version deleted 
    // or vice versa, it will compile as long as the one that you have defined 
    // matches the constness of x. 
}; 

int main(int argc, char** argv) 
{ 
    A x; 
    std::cout << &x << std::endl; 
    return 0; 
} 
+0

Функция члена 'const' может вызываться на объекте, отличном от 'const'. Я не уверен, чего вы ожидаете. –

+0

@ T.C. Это может быть, но ошибка возникает даже тогда, когда она не вызывается (когда x не является константой и удаляется только версия const). Это также происходит в противоположной ситуации (const x только с неконстантной версией). Я попытался сделать это ясно, но это, по общему признанию, сложно. –

+0

В приведенном выше коде, если вы комментируете 'const A * operator &() const {...}' и uncomment 'const A * operator &() const = delete;' компилируется для объекта '' constst '' A' , Точно так же вы можете получить его для компиляции для 'const A', комментируя/раскомментируя другую комбинацию, так что в чем ваш вопрос?Вместо всех этих комментариев в коде, возможно, попробуйте опубликовать все версии, которые не будут компилироваться. – Praetorian

ответ

4

Встроенный operator& не участвует в разрешении перегрузки ([over.match.oper]/3.3).

Для operator ,, то unary operator & или operator ->, встроенный в кандидаты набор пуст.

Say вы объявляете как исключенные перегрузки ниже

const A* operator&() const = delete; 

Независимо от того, что вы пытаетесь взять адрес const или ненаправленного constA, указанное заявление является единственным реальным кандидатом, что приводит к ошибке компиляции.

Если вы прокомментируете это, то встроенный operator& будет найден по [over.match.oper]/9.

Если оператор является operator ,, то unary operator & или operator ->, и нет никаких жизнеспособных функций, то оператор считается встроенный оператор и интерпретируется в соответствии с пунктом [выражение ].

Теперь, если вы объявите, как удалили не- const перегрузки только

A* operator&() = delete; 

это не может быть вызван на const A объекта, поэтому он не будет жизнеспособным кандидатом и встроенный operator& будут найдены.

Live demo


При работе с классом, который перегружает operator&, вы можете использовать std::addressof, чтобы получить адрес экземпляра.