c \ Функции с объединениями в качестве аргументов для удовлетворения конкретных требований

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

Alg1_Foo();
Alg2_Foo();
...

Я хочу этот:

Foo(alg);

Но я не хочу передавать alg в качестве отдельного аргумента, потому что функции будут иметь много аргументов даже без него, у них будут аргументы для идентификации и / или авторизации устройства, в качестве аргумента, вне аргумента (хотя бы один из них) ), поэтому я думаю, что будет неудобно добавлять alg в качестве отдельного аргумента.

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

Foo(const SomeUnion& some_union);

Куда:

union SomeUnion {
AlgId alg_id;
alg1::SomeStruct alg1_some_struct;
alg2::SomeStruct alg2_some_struct;

SomeUnion(alg1::SomeStruct some_struct) { alg1_some_struct = some_struct; };
SomeUnion(alg2::SomeStruct some_struct) { alg2_some_struct = some_struct; };
};

И структуры конкретных алгоритмов будут выглядеть так:

namespace alg1 {
struct SomeStruct {
static const AlgId alg_id = ALG1;
. . .
};
}

Поэтому, если вы хотите выполнить, скажем, alg1, мы передаем соответствующую структуру в Foo, и она работает в C ++, скажем,

alg1::SomeStruct a;
Foo(a);

Но я хочу, чтобы моя библиотека поддерживала возможности чистого C. Конечно, мне нужно:

  1. удалить ссылки и заменить их указателями;

  2. удалить пространства имен (мы все еще можем эмулировать их с помощью структур (этот поток может быть полезен для тех, кто заинтересован: Пространства имен в C);

  3. заменить C ++ — стиль определения структур на тот же из C и определить также имя в пространстве имен тегов (typedef struct tagStruct {…} Struct;);

  4. удалить функции из внутренних структур и союзов.

Но хотя я не могу понять, возможно ли выполнить то, что я хочу сделать с помощью поддержки C … Видите ли вы путь? Или просто проще передать alg_id в качестве отдельного аргумента, чтобы не связываться с объединениями и структурами (но я хочу избежать этого, если это возможно)?

1

Решение

Мне это кажется типичным случаем, когда кто-то пытается решить проблему «неправильным путем».

Если у вас есть «много аргументов» для функции, то с помощью struct Это хорошо. Но скрывая «какую функцию вы на самом деле вызываете» внутри такого structи затем имея несколько вариантовstruct внутри unionСейчас мы пытаемся вложить слишком много в одну функцию. Начните разделять функцию так, чтобы она занимала всего одну struct — удали свой union как аргумент — это просто неправильно. [Я работал с кодом, который делает подобные вещи — шансы проникнуть в некоторый код, который делает неправильную вещь и вызывает некоторые трудно найти ошибку, потому что вы передали неправильный тип union Аргументы в функцию делают это действительно плохим решением. Если вы передаете неправильный тип структуры простым функциям, то компилятор скажет вам. Если вы заполните неправильную часть объединения, код, использующий «правильную» часть структуры, получит «странные» данные [вполне возможно, неопределенное поведение] — этот тип ошибки может быть чертовски трудным для поиска.

Так что да, разделите ваши функции, удалите объединение!

Редактировать:
Одно из соображений, которое приходит на ум, если вы хотите иметь простой и последовательный интерфейс, это то, что у вас есть заводская функция, которую вы передаете alg_id to, который возвращает указатель на функцию. К сожалению, если интерфейс для каждой функции, как я предполагаю, имеет другую структуру, то у вас все еще есть возможность смешать структуры данных и функции, но это сокращает количество «опубликованных функций» — фактически, эти функции вообще не должны быть видны за пределами модуля [библиотеки или даже объектного файла], который их предоставляет.

3

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

Других решений пока нет …

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