Определите псевдоним и функцию получения/установки, только если тип существует в классеC++

Программы на C++. Форум разработчиков
Ответить
Гость
 Определите псевдоним и функцию получения/установки, только если тип существует в классе

Сообщение Гость »


Мне предоставлен набор классов, которые я не могу изменить. (Для любопытных: они автоматически генерируются из моделей Simulink). К сожалению, эти классы делают слишком много вещей общедоступными. Итак, я решил написать класс интерфейса для всех этих классов, который инкапсулирует их и делает их использование немного безопаснее. Однако у меня возникли проблемы с написанием одного класса интерфейса (шаблона), который работал бы для всех возможных классов.
Большинство классов определяют структуру под названием MyStruct, которую я необходимо использовать внутри класса интерфейса. Однако я не хочу использовать это имя по разным причинам и вместо этого хотел бы использовать псевдоним внутри класса интерфейса. В итоге у меня получился следующий код:

Код: Выделить всё

// Classes to interface with
class MyClass1
{
public:
struct MyStruct
{
double f1;
double f2;
} _myVar {};
};

class MyClass2
{
public:
struct MyStruct
{
double g1;
double g2;
double g3;
} _myVar {};
};

class MyClass3
{};

// Interface class
template
class Interface
{
public:
using MyAlias = typename T::MyStruct;

void setVar(const MyAlias& newVar) {_object._myVar = newVar;};

void doSomething()
{
MyAlias inputs {};
}
private:
T _object {};
};

// Main function
int main()
{
Interface i1; // compiles fine
Interface i2; // compiles fine
Interface i3; // compile error: no type named ‘MyStruct’ in ‘class MyClass3’
return 0;
}

Это не удается скомпилировать, поскольку MyClass3 не определяет тип MyStruct. Следовательно, псевдоним не может быть определен.
Я пытался определить псевдоним и метод только в том случае, если тип определен, и наткнулся на концепцию SFINAE. К сожалению, я не могу использовать в своем коде ничего из стандартной библиотеки. Поэтому такие вещи, как std::enable_if или std::void_t, не обсуждаются. Искусственный интеллект предложил следующие решения для псевдонима и метода:

Код: Выделить всё

template
struct check_mystruct {using type = void; };
template
struct check_mystruct { using type = typename U::MyStruct; };
using MyAlias = typename check_mystruct::type;

Код: Выделить всё

template
void setVar(const U& newVar) {_object._myVar = newVar;};
void setVar(...) { /* do nothing */ };
Насколько я понимаю, это должно сработать. Частичная специализация структуры check_mystruct и шаблонная версия метода должны использоваться только в том случае, если S::MyStruct существует.
Однако, если я объединил их в исходную программу следующим образом: :

Код: Выделить всё

// Classes to interface with
class MyClass1
{
public:
struct MyStruct
{
double f1;
double f2;
} _myVar {};
};

class MyClass2
{
public:
struct MyStruct
{
double g1;
double g2;
double g3;
} _myVar {};
};

class MyClass3
{};

// Interface class
template
class Interface
{
public:
template
struct check_mystruct {using type = void; };
template
struct check_mystruct { using type = typename U::MyStruct; };

using MyAlias = typename check_mystruct::type;

template
void setVar(const U& newVar) {_object._myVar = newVar;};
void setVar(...) { /* do nothing */ };

void doSomething()
{
MyAlias inputs {};
}
private:
T _object {};
};

// Main function
int main()
{
Interface i1; // compiles fine
Interface i2; // compiles fine
Interface i3; // compiles fine

i1.doSomething(); // compile error: In instantiation of ‘void Interface::doSomething() [with T = MyClass1]’: variable or field ‘inputs’ declared void
i2.doSomething();
i3.doSomething();

return 0;
}

Я получаю сообщение об ошибке компиляции

Код: Выделить всё

main.cpp: In instantiation of ‘void Interface::doSomething() [with T = MyClass1]’:
main.cpp:58:19:   required from here
main.cpp:44:17: error: variable or field ‘inputs’ declared void
44 |         MyAlias inputs {};
|                 ^~~~~~
So, the alias is set to void even though MyClass has a type MyStruct. I do not understand this. Can someone explain what went wrong? Is there another way to achieve what I am trying to do?


Источник: https://stackoverflow.com/questions/781 ... in-a-class
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»