Использование boost :: ref для указания намерения в соглашениях по кодированию

Когда функции принимают неконстантные ссылки в качестве аргументов, они могут создать трудно читаемый код, потому что на вызывающем сайте не очевидно, какие входные данные могут быть изменены. Это привело к тому, что некоторые условные обозначения в коде заставляют использовать указатели, например

void func(int input, int* output);

int input = 1, output = 0;
func(input, &output);

вместо

void func(int input, int& output);

int input = 1, output = 0;
func(input, output);

Лично я ненавижу использовать указатели из-за необходимости проверять нулевое значение. Это заставило меня задуматься о том, может ли boost :: ref (или std :: ref для C ++ 11) использоваться для обозначения намерения следующим образом:

void func(int input, int& output);

int input = 1, output = 0;
func(input, boost::ref(output));

Это будет использоваться в качестве соглашения о кодировании компании. Мой вопрос: есть ли причины, по которым это не будет хорошей идеей?

3

Решение

Это неплохая идея, но она на самом деле не соблюдается (как отмечает ПетрНыч). Это фактически просто комментарий.

Мы можем сделать лучше, хотя:

template <typename T>
class output_argument
{
public:
template <typename U>
friend output_argument<U> out(U& ref);

T& get() const
{
return mRef;
}

operator T&() const
{
return get();
}

private:
explicit output_argument(T& ref) :
mRef(ref)
{}

output_argument& operator=(const output_argument&); // not defined

T& mRef;
};

template <typename U>
output_argument<U> out(U& ref)
{
return output_argument<U>(ref);
}

Предоставление:

void foo(int x, output_argument<float> f)
{
int i = static_cast<int>(f);

f.get() = static_cast<float>(i + x);
}

int main()
{
float f = 5.0f;

//fails: foo(1, f);
foo(1, out(f));
}

Но обычно такие утилиты не нужны, потому что имя функции должно передавать то, что происходит с аргументами: swap(x, y) довольно четко изменяет аргументы! И возвращать значения следует с типом возврата, что еще больше ограничивает возможности использования этой утилиты.

3

Другие решения

Это соглашение о кодировании компании может быть легко (по ошибке, конечно) нарушено так:

void func(int input, int& output);

int input = 1, output = 0;
func(boost::ref(input), output);

это компилируется и работает нормально — но вводит в заблуждение читателей.

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

void copyTo(int input, int& output);

В современной IDE — вы можете видеть, читая, что делает функция.


Может быть, лучше соглашение о кодировании компании будет наоборот, используя boost :: cref:

void func(int input, int& output);

int input = 1, output = 0;
func(boost::cref(input), output);

Здесь ошибки как с boost :: ref невозможны …

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector