C ++ неявные преобразования и двусмысленность в перегруженной функции вызова
-
29-09-2019 - |
Вопрос
Я сталкиваюсь с следующей проблемой: у меня есть класс V (скажем вектор), из которого я могу производить два класса: CI и I (подумайте о Const_iterator и ITERATOR). Если у меня есть const v, то я могу производить только Ci (снова подумайте о итераторе и Const_iterator).
По сути, я хотел бы поставить (Const V & V) с (Ci Ci) и (V & V) с (i i). Более того, я хотел бы иметь возможность по-прежнему передавать V OBJ непосредственно к функциям, ожидая I или Ci, следовательно, неявные преобразования от V и Const V к CI и I.
Проблема, которую я сталкиваюсь с тем, что в то время как перегруженные функции могут различать (Const V & V) и (V & V), они не могут «различать» между (Ci Ci) и (I I I), когда я передаю V OBJ.
В коде:
struct V {};
struct I
{
I( V& v ){}
};
struct CI
{
CI( const V& v ){} //I would like to say const only
};
void fun( I i )
{
double x = 1.0;
}
void fun( CI ci )
{
double x = 2.0;
}
void fun2( V& v )
{
double x = 1.0;
}
void fun2( const V& v )
{
double x = 2.0;
}
Обратите внимание, что я мог бы определить оператор преобразования в V (это эквивалентно?) Вместо того, чтобы определить конструкторов в CI и I. Теперь:
V v;
const V cv;
fun2( v );
fun2( cv );
fun( v ); //AMBIGUOUS!
fun( cv );
Есть ли способ решить эту проблему без добавления любого дополнительного косвествия (т.е. забавные функции не могут быть изменены, а v должен быть передан непосредственно для удовольствия, но вы можете изменить все остальное).
Спасибо заранее за любую помощь!
Решение
Что вам нужно здесь, явные конструкторы:
struct I
{
explicit I( V& v ){}
};
struct CI
{
explicit CI( const V& v ){} //I would like to say const only
};
Слишком много программистов C ++ пропускают четкое слово для конструкторов. Все одинарные, параметризованные конструкторы должны быть явными по умолчанию. Неявные конструкторы приглашают проблемы с двусмысленностью, подобными таким образом, как они, а также приводящие к очень волнностям, процессы конвертации кольцевой развязки, которые могут легко привести к проблематичному и очень неэффективному коду.
Теперь вы устанавливаются, проблема неоднозначности решена. Без явных конструкторов вы не можете предотвратить эту проблему двусмысленности.
Для клиентского кода вам нужно изменить его, чтобы быть явным в его преобразованиях:
V v;
const V cv;
fun2( I(v) );
fun2( CI(cv) );
fun( I(v) );
fun( CI(cv) );
Такой синтаксис теперь потребуется, чтобы построить объекты I или CI, но это хорошо: никто не может случайно вводить проблемы двусмысленности.
Другие советы
Как насчет просто используя typedef
S?
typedef V& I;
typedef const V& CI;
Редактировать:
Нет. Смотрите комментарии :)