Здравствуйте, unreg_flex, Вы писали:
_>Возможно ли такое сделать в принципе?
_>Может нужно завести дополнительный параметр в шаблоне (например int), _>но как при каждом инстанцировании увеличивать его на 1 ума не приложу.
_>Преведствуются любые решения, даже с использованием MS specific фичек.
Можно взять на использование __COUNTER__ (MS. spec.)
Переносимее и менее работающее будет __LINE__.
Здравствуйте, Roman Odaisky, Вы писали:
RO>А что мешает использовать динамическую память? Например, просто создавать и возвращать boost::shared_ptr?
По идее мешает использование буста, а собственный лесипед городить ради такой мелочи не хочется.
RO>Назови свою конечную цель, и тогда тебе смогут помочь более обоснованно.
Здравствуйте, _nn_, Вы писали:
__>Здравствуйте, unreg_flex, Вы писали:
_>>Возможно ли такое сделать в принципе?
_>>Может нужно завести дополнительный параметр в шаблоне (например int), _>>но как при каждом инстанцировании увеличивать его на 1 ума не приложу.
_>>Преведствуются любые решения, даже с использованием MS specific фичек.
__>Можно взять на использование __COUNTER__ (MS. spec.)
Почитал, попробовал, получилось
Полезная штучка, жаль что нестандартно, ну да ладно.
Особенно понравилось, что теперь полностью самому можно управлять специализацией.
Хочу совпадает, нехочу не совпадает
__>Переносимее и менее работающее будет __LINE__.
Это к сожалению примерно как #define TRUE (rand()%10000)
Здравствуйте, unreg_flex, Вы писали:
_>Преведствуются любые решения, даже с использованием MS specific фичек.
template<class T, class Tag>
T** F(T *p) {
static T *sptr=0;
sptr=p;
return &sptr;
}
class my_tag {};
pp1=F<int, my_tag>(p1);
class another_tag {};
pp2=F<int, another_tag>(p2);
class yet_another_tag {};
pp3=F<float, yet_another_tag>(p3);
Здравствуйте, unreg_flex, Вы писали:
_>Возможно ли такое сделать в принципе?
_>Может нужно завести дополнительный параметр в шаблоне (например int), _>но как при каждом инстанцировании увеличивать его на 1 ума не приложу.
_>Преведствуются любые решения, даже с использованием MS specific фичек.
Но думаю, что избавляться не надо и даже нежелательно. Потому что приведение к указателю на функцию (будь то сишная или бустовская) маскирует семантику. А у тебя довольно специфичная вещь, чтобы абстрагироваться от неё.
Это все конечно очень хорошо и понятно, только вот ни reset ни delete ... некому будет вызывать
Суть в следующем:
Пользователь вызывает некоторый шаблонный метод A и передает в параметрах указатель на объект, этот метод инстанцирует другой шаблонный метод B, в недрах которого нужен этот указатель, но параметры метода B пофиксены и в дальнейшем берется его адрес (указатель на метод) и засовывается в список, поэтому никакие биндеры тут не пройдут. Список параметров метода B менять нельзя. Однако хочется при его инстанцировании зашить в его тело этот указатель.
Я сам прекрасно понимаю что можно сделать всякоразные списочки указателей, шаред_птр-ы и прочее, но нехочется для рубки березки использовать лазерную пушку
Пока на данный момент лучшее решение это умный указатель.
В принципе это все не к спеху и особо никому не надо, это так, программирование для удовольствия, хочется найти красивое решение без оверхеда.
В принципе, как оказалось, страшно даже не то что он обнуляется в каждом модуле,
а то что написав:
template< class T >
void f() {
...
g< T,__COUNTER__ >();
...
}
при инстанцировании f любым типом, будем всегда получать вызов g< T,0 >();
т.е. __COUNTER__ не будет менятся, поскольку он используется один раз.
Поэтому его надо будет явно передавать, или использовать макрос, ни того ни другого нехочу
Здравствуйте, unreg_flex, Вы писали:
_>Суть в следующем: _>Пользователь вызывает некоторый шаблонный метод A и передает в параметрах указатель на объект, этот метод инстанцирует другой шаблонный метод B, в недрах которого нужен этот указатель, но параметры метода B пофиксены и в дальнейшем берется его адрес (указатель на метод) и засовывается в список, поэтому никакие биндеры тут не пройдут. Список параметров метода B менять нельзя. Однако хочется при его инстанцировании зашить в его тело этот указатель.
Отвратительное описание задачи. Намертво перемешаны время компиляции и время исполнения. Зачем, почему...
Множество вызовов метода с одинаковой сигнатурой приводят к созданию ровно одного воплощения шаблона. Поэтому получить множество объектов только средствами компилятора (размещённых в static storage) — не выйдет.
Или выйдет с хаками, работающими в пределах одной единицы трансляции.
О, кстати! Пришла в голову идея хака, действующего глобально. Точнее, обеспечивающего независимость между единицами трансляции.
// f.hnamespace { // unnamedtemplate<int N> struct unique_tag{};
}
#define UNIQUE_TAG unique_tag< __COUNTER__ >
template<class Tag>
struct traits
{
template<class T>
T** fun(T* v)
{
static T var = 0;
delete var;
var = v;
return &var;
}
};
#define FUN traits< UNIQUE_TAG >::fun
// a.cpp#include"f.h"
.....
int** ppx = FUN(new int); // traits< unnamed_a::unique_tag<0> >::fun<int>int** ppy = FUN(new int); // traits< unnamed_a::unique_tag<1> >::fun<int>
.....
// b.cpp#include"f.h"
.....
int** ppz = FUN(new int); // traits< unnamed_b::unique_tag<0> >::fun<int>int** ppt = FUN(new int); // traits< unnamed_b::unique_tag<1> >::fun<int>
.....
int** ptrs[3];
for(int i=0; i!=3; ++i) ptrs[i] = FUN(new int); // traits< unnamed_b::unique_tag<2> >::fun<int>
// т.е. при инициализации в цикле - получим указатели на один и тот же объект var.void foo(int**(*f)(int*))
{
int** ppa = f(new int);
int** ppb = f(new int);
}
foo(FUN); // и здесь внутри foo будет фигурировать один и тот же traits< unnamed_b::unique_tag<3> >::fun<int>
Обрати внимание на два последних случая.
Если это то, что тебе хочется — используй compile-time-размещение объектов.
Если же тебе хочется, чтобы все объекты были уникальны — не заморачивай голову, делай в run-time. Например, со списками.
Здравствуйте, Кодт, Вы писали:
К>Отвратительное описание задачи. Намертво перемешаны время компиляции и время исполнения. Зачем, почему...
Согласен, спешил, да и с терминологией у меня плохо
К>Множество вызовов метода с одинаковой сигнатурой приводят к созданию ровно одного воплощения шаблона. Поэтому получить множество объектов только средствами компилятора (размещённых в static storage) — не выйдет.
Вот это и плохо
Почитал пост с хаком через friend, плохо понял как это работает, да и оставлять такое в коде страшно.
Хотя возможности такой штучки действительно впечатляют.
Видимо не используя хаков, без динамической памяти тут не обойтись.
Приведу код, надеюсь так будет понятней:
typedef bool (Manager::*Listener)(double data);
class Manager {
public:
void AddListener(int nSlot,Listener pListener) {
// тут производится добавление pListener в некоторый список
...
}
...
}
Этот класс менять нельзя.
Но хочется добавить в класс производный от Manager несколько методов, которые будут автоматически
генерировать некорые часто используемые типы Listener-ов (дабы не писать их каждый раз ручками),
например так:
class CoolManager: public Manager {
public:
template< class Object >
void AddCoolListener(int nSlot,Object *pObject) {
Manager::AddListener(nSlot,&CoolManager::CoolListener< Object >);
}
...
private:
template< class Object >
bool CoolListener(double data) {
// проблема в том что тут нужен указатель pObject, которая передается в AddCoolListener
// по сути ее надо сюда как-то зашить
// но использовать динамическую память или списки не очень хочется
}
}
Хочу что-бы юзер писал без макросов:
SomeManager1.AddCoolListener(SomeSlot1,&SomeObject1);
SomeManager2.AddCoolListener(SomeSlot2,&SomeObject2);
Идея заключалась в использовании шаблонной функции со статической переменной внутри
для хранения в ней указателя pObject. Но юзер каждый раз передает разные указатели.
Число этих указателей равно числу вызовов AddCoolListener< ... >,
вот я и хотел заставить компилятор при каждом вызове AddCoolListener генерировать новую
копию CoolListener и функцию с новым статическим указателем внутри (для использования внутри CoolListener)
К>О, кстати! Пришла в голову идея хака, действующего глобально. Точнее, обеспечивающего независимость между единицами трансляции.
Вот за это +3, хоть проблему это не решает (есть макросы), но это интересный способ увеличить диапазон действия __COUNTER__.
Вроде просто, но сам я не догадался
Кстати, а почему это хак???