C ++ неявные преобразования и двусмысленность в перегруженной функции вызова

StackOverflow https://stackoverflow.com/questions/3112602

Вопрос

Я сталкиваюсь с следующей проблемой: у меня есть класс 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, но это хорошо: никто не может случайно вводить проблемы двусмысленности.

Другие советы

Как насчет просто используя typedefS?

typedef V& I;
typedef const V& CI;

Редактировать:

Нет. Смотрите комментарии :)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top