LINUX.ORG.RU

Указатель на шаблонную функцию-член класса как параметр шаблона?

 , ,


0

1

Есть некий класс A, у него есть метод call который должен вызывать у класса B некоторый метод foo, bar или еще какой то:

class A{
    template<typename C, ... func ... > void call(C& c, ...){
    // длинная свитч-портянка в ней определеяется int I и
         c->func<I>(...);
    }
};
class B{
   template <int I> void foo(...){}
   template <int I> void bar(...){}
};

использоваться должно как то так

A a;
a.call<... &B::foo ...>(b);
...
a.call<... &B::bar ...>(b);

типы аргументов у foo и bar разные.

Общий смысл - не дублировать портянку в A::call. Чо то пока не выходит ни так ни эдак;-(

★★★★★

Последнее исправление: cetjs2 (всего исправлений: 2)

Скорее «указатель на что-то несуществующее». У шаблонов не может быть адреса, они лишь описание того, как создать что-то адресуемое.

Я бы попробовал передавать в call шаблонный функтор, который будет вызывать нужный метод C.

xaizek ★★★★★
()
Последнее исправление: xaizek (всего исправлений: 1)

А тебе вообще надо знать, что это метод какого-то класса? если нет, то можно использовать std::function, тогда код резко упростится:

class A {
    template<typename ReturnedType, typename ... ArgTypes>
    void call(std::function<ReturnedType(ArgTypes)> f, ArgTypes... args) {
        f(std::forward<ArgTypes>(args));
    }
};

и вызывать примерно так:

A a;
a.call([&b](int arg){b.foo<int>(arg);});

p.s. код не проверял на компилябельность, но идея должна быть понятна

EugeneBas ★★
()

Не нужна тут std::function, достаточно отдавать лямбду в шаблонный call.

anonymous
()
Ответ на: комментарий от xaizek

Можно просто класс у которого шаблонный метод с заданным именем дёргает то что нужно.

Спасибо!

AntonI ★★★★★
() автор топика
Ответ на: комментарий от EugeneBas

Нет, так не получится. То есть Ваш код рабочий, но он не решает поставленной задачи.

AntonI ★★★★★
() автор топика
Ответ на: комментарий от AntonI

аа, проглядел, что надо метод выбрать на основе I… Есть подозрение, что так не будет работать. I - это константа, которая должна быть известна на этапе компиляции и подставляется при инстанциации шаблонов, а ты пытаешься на основе switch решить, в какой шаблон ее подставить, т.е. пытаешься перенести это решение в рантайм - так не получится. Тут надо либо заранее проинстанциировать все шаблоны и передавать уже указатели на функции для исполнения (как в моем примере), либо убирать параметр шаблона в аргументы методов (переносить в рантайм), либо делать шаблонным весь класс (чтобы опять же принять решение о значении константы заранее).

EugeneBas ★★
()
#include <iostream>

#define SYM(NAME) _Wrap_##NAME

#define DEFSYM(NAME) \
    template <typename T, auto... VArgs> \
    struct SYM(NAME) { \
      template <typename... Args> \
      static void run(T& t, Args&&... args) { t.template NAME<VArgs...>(std::forward<Args>(args)...); } \
    }

struct A {
    template<typename C, template <typename, int> class S> 
    void call(C& c){
      S<C, 1>::run(c);
      S<C, 2>::run(c);
    }
};

struct B {
    template <int I> 
    void foo() { std::cout << "foo: " << I << std::endl; }
    template <int I> 
    void bar() { std::cout << "bar: " << I << std::endl; }
};

DEFSYM(foo);
DEFSYM(bar);

int main () {
    A a;
    B b;
    
    a.call<B, SYM(foo)>(b);
    a.call<B, SYM(bar)>(b);
}

(:

Kuzy ★★★
()
Ответ на: комментарий от EugeneBas

Есть уверенность что это работает. Именно так - I определяется в рантайме через свитч.

AntonI ★★★★★
() автор топика
Ответ на: комментарий от EugeneBas

Нет, не нужно.

switch (...) {
case ...: c.foo<1>(...);
case ...: c.foo<2>(...);
case ...: c.foo<N>(...);
}

Насколько я понял, ТС что-то такое хочет соорудить.

Siborgium ★★★★★
()
Ответ на: комментарий от Siborgium

Да. Это способ вытащить рантайм свитч наружу цикла.

AntonI ★★★★★
() автор топика

Если честно, как по мне то задача до конца не раскрыта. Как I рассчитывается? Как определяется какие аргументы передаются в метод B и как они передаются? Вот эти многоточия в сигнатурах понятны только автору, а ведь они сильно влияют на результат.

Пока я вижу так что каждый метод класса B имеет свой набор аргументов и несколько реализаций специализированных по I? Типа оптимизации какой-то? И мы вызываем метод класса B и хотим скрыть логику выбора специализации в классе A и сделать ее более удобной в плане сопровождения? При этом аргументы для метода B мы задаем в A::call, правильно?

anonymous
()
Ответ на: комментарий от Siborgium

ну тогда нужно больше данных, например идентичны ли сигнатуры методов foo и bar? вообще, в каком контексте мы пытаемся решить эту задачу? может она вообще элегантнее решается через динамический полиморфизм, а не через статический?

EugeneBas ★★
()
Ответ на: комментарий от EugeneBas

например идентичны ли сигнатуры методов foo и bar?

Неважно, решение задачи от этого не меняется.

вообще, в каком контексте мы пытаемся решить эту задачу?

Неважно.

может она вообще элегантнее решается через динамический полиморфизм, а не через статический?

Неважно. Динамика не бывает элегантнее, это необходимое зло.

Siborgium ★★★★★
()
Ответ на: комментарий от Siborgium

не соглашусь, динамический полиморфизм всегда элегантнее свичей и читается всегда проще, чем синтаксис шаблонов

EugeneBas ★★
()

Вместо того что-бы просто программировать вы оверинжинирите банальные вещи.

anonymous
()
Ответ на: комментарий от EugeneBas

С таким подходом самый элегантный способ решить любую задачу это кнопка «СДЕЛАТЬ ХОРОШО».

Вася и Толя решили перебраться через реку. Вася пошёл искать мост или построить его. А Толя решил уехать в столицу обучится физике, сделать расчёты для катапульты провести испытания, наладить изготовление катапульт и когда всё будет отлажено, он вернётся к реке и его перекинет спроектированная и оттестированная катапульта. Да, прикольно, но ЗАЧЕМ?

anonymous
()
Ответ на: комментарий от anonymous

ну если играть в максимализм, то ТСу не стоило ни с шаблонами связываться, ни с наследованием, ни на форум писать, а бахнуть процедурный код в стиле си и ехать дальше

EugeneBas ★★
()
Ответ на: комментарий от EugeneBas

может она вообще элегантнее решается через динамический полиморфизм, а не через статический?

динамический полиморфизм всегда элегантнее свичей

Так элегантнее свичей или статического полиморфизма?

читается всегда проще, чем синтаксис шаблонов

Это никого не волнует.

ТСу не стоило ни с шаблонами связываться, ни с наследованием, ни на форум писать, а бахнуть процедурный код в стиле си и ехать дальше

Зачем писать процедурный код в стиле си, если портянку можно сгенерировать компилятором?

Siborgium ★★★★★
()
Последнее исправление: Siborgium (всего исправлений: 1)
Ответ на: комментарий от Siborgium

Элегантнее свичей и статического полиморфизма. Удобочитаймость тоже учитывается.

читается всегда проще, чем синтаксис шаблонов

Это никого не волнует.

Ну тебя не волнует, но не говори за всех. Меня это волнует всегда, т.к. люди помимо написания кода еще занимаются и его поддержкой. И далеко не всегда это одни и те же люди.

Зачем писать процедурный код в стиле си, если портянку можно сгенерировать компилятором?

ответный вброс, не надо это всерьез воспринимать

EugeneBas ★★
()
Ответ на: комментарий от AntonI

Ну вот поэтому я и говорю, что нужно больше данных, тут оказывается есть ограничения по производительности. Кстати, а тормозит-то точно на этом моменте, или это попытка преждевременной оптимизации?

EugeneBas ★★
()
Ответ на: комментарий от EugeneBas

Лор такой лор… Вроде задача и правильно поставлена (в условии есть все нужное и ничего лишнего), и решил ее @xaizek в первом же комменте - но обязательно прибежит пара анонимусов и еще кто то и начнут рассказывать что ТС все делает не то и не так. И вообще надо взять лисп/СУБД/динамический полиморфизм.

Не надо так. Если конечно у Вас не стоит цель прокачать скор…

AntonI ★★★★★
() автор топика
Ответ на: комментарий от AntonI

Вроде задача и правильно поставлена

Поддерживаю анонимуса.

pathfinder ★★★★
()
Ответ на: комментарий от EugeneBas

Элегантнее свичей и статического полиморфизма.

Ты не знаешь что такое статический полиморфизм. А так же то, что рождено здесь - никакого отношения к нему не имеет. Это просто нелепый колхоз на си с классами от того, кто выучил пару трюков. Причём старых.

Ты думаешь любой, кто хоть что-то знает о производительности будет собирать код компилятором 10летней давности? Нет, конечно. Поэтому он специально создаёт себе маня-мирок в котором никто не укажет ему даже на то, что даже те самые пару трюков устарели.

Ну и, конечно же, дин-полиморфизм никак не избавит тебя от свича. Как ты переведёшь то же самое число в нужный тебе инстанс? Никак без свича.

При это статический полиморфизм позволяет это сделать без проблем.

Ну тебя не волнует, но не говори за всех. Меня это волнует всегда, т.к. люди помимо написания кода еще занимаются и его поддержкой. И далеко не всегда это одни и те же люди.

Ты перепутал методичку. То, что рядовая обезьяна не может поддерживать статический полиморфизм(просто в силу того, что не может в него) - это не значит, что его нельзя поддерживать.

С таким же успехом эта обезьяна не сможешь поддерживать какой-нибудь хром, но это не означает, что его нельзя поддерживать и читать.

Давай ещё раз. Требует большего уровня от читателя не означает невозможность. Это означает невозможность для более низкого уровня читателя.

anonymous
()

функцию-член

Чудно всё у вас в плюсах … Переполнения и прочее …

Сгущаются на небе тучи
Владимир переполнил кучу ...

Владимир

anonymous
()
Ответ на: комментарий от anonymous

О фанате C++ в армии.

Сержант спрашивает солдата.  
Иванов, о чем ты думаешь глядя на кирпич?  
О C++.  
Так это же кирпич.  
Ну и что? 
Я всегда о C++ думаю.
anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.