2014-11-07 5 views
4

Я хочу, чтобы экземпляр класса преобразовывался в int при использовании оператора присваивания. Поэтому я написал этот код:Как удалить функцию из разрешения перегрузки?

struct X 
{ 
    X() = default; 
    X& operator=(int) { std::cout << "operator=(int)\n"; return *this; } 
    operator int() { return 0; } 
}; 

int main() 
{ 
    X a, b; 
    a = b; 
} 

Но он не называется. Это связано с тем, что он вызывает неявный оператор присваивания копий, который является точным соответствием для аргумента. Я хочу, чтобы мой код сначала вызывал оператор преобразования на b, а затем привязывал возвращаемое значение int к operator=().

Есть ли синтаксис, чтобы сообщить компилятору «не считать эту функцию»? Другими словами, как удалить функцию из разрешения перегрузки?

Я пробовал использовать шаблоны на операторе копирования-присваивания, чтобы я мог делать SFINAE, но, я думаю, это просто создает другую функцию, поэтому не-шаблон всегда будет лучшим совпадением.

+0

Nope. Вы можете сделать ошибку, чтобы вызвать что-то (путем удаления его), но вы ничего не можете удалить. –

+0

Вы можете просто указать его явно: a = static_cast (b); 'Это также было бы более интуитивно понятным поведением для кого-то другого, просматривающего ваш код. – Praetorian

ответ

4

Неявно созданный оператор присваивания остается лучшей версией, даже если вы его используете = delete, т. Е. Вы получите ошибку вместо выбранной другой версии. Я бы рекомендовал просто экспедиторскую логику в зависимости от обстоятельств и не пытайтесь удалить функцию:

X& X::operator= (X const& other) { 
    return (*this) = static_cast<int>(other); 
} 

Следует признать, что потенциально позволяет дополнительную неявную последовательность преобразования, которые не могут иначе быть разрешены:

T -> X -> int 

К встретите эту возможность, вы бы добавили еще одного оператора назначения:

template <typename T> 
X& X::operator= (T&& other) { 
    int arg = other; 
    return (*this) = arg; 
} 
+0

Я пробовал маркировать оператор присваивания 'private', но это тоже не работает. – japreiss

+0

Спасибо, но я думаю, что я буду придерживаться роли извне, как сказал Преториан. Для пользователей моего кода оператор копирования-назначения сделает очень неожиданные вещи. :) –

+0

@japreiss Разрешение перегрузки происходит до контроля доступа, поэтому, если функция закрыта, защищена или иным образом не рассматривается. –

0

для предотвращения создания компилятором функции по умолчанию, вы должны объявить eme private (обратите внимание, что вам не нужно определять тему).
для получения дополнительной информации, я предлагаю вам, что прочитать эффективный C++ по Scot Meyers главе 2, пункт 6.

+0

Даже если я объявлю их частным, что не изменит, как работает разрешение перегрузки. Он по-прежнему будет выбирать обычный оператор копирования, а не перегруженный. –

0

Просто напишите

a = static_cast<int>(b);