Можно ли вызывать шаблонные функции в шаблонных производных классах из указателя на базу?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Можно ли вызывать шаблонные функции в шаблонных производных классах из указателя на базу?

Сообщение Anonymous »

У меня есть контейнер стираемого типа для хранения различных классов, отвечающих определенным простым требованиям. Цель состоит в том, чтобы предоставить согласованный интерфейс для аналогичных классов контейнеров данных, который затем позволит пользователям писать и использовать свои собственные версии.
Мои общие элементы контейнера могут принимать любой класс, который соответствует определенным свойствам, и передает их, позволяя каждому экземпляру класса, приемлемого для Element, использовать свои собственные реализации требуемых функций.
На данный момент все поддерживаемые функции в Elements< Класс /code> предназначен для нешаблонных функций. Можно ли использовать подобный интерфейс со стиранием типов для поддержки шаблонных функций? В частности, мне нужна функция для преобразования между классами разных типов, которые содержатся в классе Elements.
Если мой интерфейс со стертым типом выглядит примерно так:

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

template 
concept HasFoo = requires(T t) {
{ t.foo() } -> std::same_as;
};

template 
concept IsUserDefinedElements = requires(T) {
// ... other generic requirement ... //
requires HasFoo;
};

struct ElementsInnerBase {
virtual ~ElementsInnerBase() {}
virtual int foo();
};

template 
struct ElementsInner final : public ElementsInnerBase {
// Constructors from T (copy and move variants).
explicit ElementsInner(const T &x) : _value(x) {}
explicit ElementsInner(T &&x) : _value(std::move(x)) {}

// Invoke required methods directly
int foo() final {
return _value.foo();
}

// Elements object
T _value;
};

class Elements;

template 
concept IsGenericallyConstructableElements = requires(T) {
requires IsUserDefinedElements;
std::negation::value;
};

class Elements {
public:
// Default constructor
Elements();

public:
template 
requires(IsGenericallyConstructableElements)
explicit Elements(T &&x) :
_ptr(std::make_unique(std::forward(x)))
{}

// Foo
int foo() {
return _ptr->foo();
}

private:
// Pointer to the inner base elements
std::unique_ptr _ptr;
};
Отдельный класс, подобный элементу, может выглядеть примерно так.

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

struct ElementsA {
int foo();
// ... A-specific details ... //
};

struct ElementsB {
int foo();
// ... B-specific details ... //
};

int run_foo(Elements e) { return e.foo(); }

int main() {
ElementsA a;
ElementsB b;

int aOut = run_foo(a);
int bOut = run_foo(b);

return 0;
}
Можно ли добавить какую-нибудь шаблонную функцию

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

template 
T convert();
в класс Elements. Экземпляры функции преобразования в каждом классе Element-подобных могут выглядеть примерно так:

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

struct ElementsA {
int foo();
ElementsB convert() { ElementsB (*this); } // conversion could be arbitrarily complex
};

struct ElementsB {
int foo();
ElementsA convert() { ElementsA(*this); }
};

int some_process(Elements e) {
// ... generic processes on e ... //

ElementsB b = e.convert ();
// ... B-specific process ... //
}

int main() {

ElementsA a;
int aOut = some_process(a);

return 0;
}
Я видел, что шаблон посетителя можно использовать для вызова шаблонных функций в производных классах из указателя на базу (аналогично этому вызову шаблонной функции производного класса), но поскольку производный класс в этом экземпляре ElementsInner является шаблонным, я не понимаю, как это можно применить здесь без непосредственного создания шаблона класса Elements, что лишило бы смысла стирания типа.
Стирание типов важно в этом контексте, поскольку оно позволяет мне определить поведение по умолчанию для функций, которые пользователи могут не захотеть или не должны определять. И я мог бы просто добавить оболочки функций для вызовов функций конкретного типа, например ElementsB Convert_to_b() и т. д., но я надеялся сохранить интерфейс чистым и универсальным.

Подробнее здесь: https://stackoverflow.com/questions/793 ... s-from-a-p
Ответить

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

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

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

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

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