Всем привет. Возник у меня такой вот сабж:
Можно ли построить достаточно большую (в идеале -- бесконечную) последовательность перегруженных функций, каждая последующая из которых является более подходящей для некоего фиксированного вызова, чем предыдущая?
Здравствуйте, av, Вы писали:
av>Можно ли построить достаточно большую (в идеале -- бесконечную) последовательность перегруженных функций, каждая последующая из которых является более подходящей для некоего фиксированного вызова, чем предыдущая?
Похоже на счётчики времени компиляции.
Невероятно, но факт! Не константные значения в компайл-тайм!Автор: remark
Дата: 06.02.07
[Trick] Компайл-тайм счётчикАвтор: remark
Дата: 07.02.07
[Trick] Компайл-тайм генератор случайных чиселАвтор: remark
Дата: 07.02.07
... << RSDN@Home 1.2.0 alpha rev. 655>>
К>Похоже на счётчики времени компиляции.
К>Невероятно, но факт! Не константные значения в компайл-тайм!Автор: remark
Дата: 06.02.07
К>[Trick] Компайл-тайм счётчикАвтор: remark
Дата: 07.02.07
К>[Trick] Компайл-тайм генератор случайных чиселАвтор: remark
Дата: 07.02.07
Ага, спасибо
Собственно, я недогуглил: собственно, я и задумался над тем, как можно починить "неконстантные значения в компайл-тайм", чтобы там было более двух разных значений, но не осознал и не нашёл продолжения банкета.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, av, Вы писали:
av>>Можно ли построить достаточно большую (в идеале -- бесконечную) последовательность перегруженных функций, каждая последующая из которых является более подходящей для некоего фиксированного вызова, чем предыдущая?
К>Похоже на счётчики времени компиляции.
Если я всё правильно понял, то всё гораздо проще:
struct X0 {};
void f(X0) {}
struct X1 : X0 {};
void f(X1) {}
struct X2 : X1 {};
void f(X2) {}
int main()
{
f(X2());
}
Сами структуры легко нагенерить с помощью щаблонов:
template<unsigned I>
struct Q : Q<I-1> {};
template<>
struct Q<0> {};
Функции тогда должны выглядеть так:
void f(Q<0>) {}
void f(Q<1>) {}
void f(Q<2>) {}
Для генерации функций можно заюзать BOOST_PP:
#define DECL(z, n, _) void f(Q<n>) {}
BOOST_PP_REPEAT(100, DECL, _)
Вот тут рассматривается последовательность из 100 перегруженных функций, каждая из которых более подходящая чем предыдущая:
int main()
{
f(Q<100>());
}
По поводу бесконечной последовательности — это скорее всего не получится. Смотри в стандарте С++ Annex B. Implementation quantities. В частности рекомендованные значения:
— Direct and indirect base classes [16 384].
— Recursively nested template instantiations [17].
Здравствуйте, remark, Вы писали:
av>>>Можно ли построить достаточно большую (в идеале -- бесконечную) последовательность перегруженных функций, каждая последующая из которых является более подходящей для некоего фиксированного вызова, чем предыдущая?
К>>Похоже на счётчики времени компиляции.
R>Если я всё правильно понял, то всё гораздо проще:
<...>
R>Вот тут рассматривается последовательность из 100 перегруженных функций, каждая из которых более подходящая чем предыдущая:
R>R>int main()
R>{
R> f(Q<100>());
R>}
R>
Как я понял, ты понял неправильно. У тебя вызов не фиксированный. Добавление каждой новой функции изменяет форму вызова.
R>По поводу бесконечной последовательности — это скорее всего не получится. Смотри в стандарте С++ Annex B. Implementation quantities. В частности рекомендованные значения:
Можно принять "туземную бесконечность" (1, 2, ..., 10,
много).
... << RSDN@Home 1.2.0 alpha rev. 655>>
Здравствуйте, Кодт, Вы писали:
К>Как я понял, ты понял неправильно. У тебя вызов не фиксированный. Добавление каждой новой функции изменяет форму вызова.
К>Можно принять "туземную бесконечность" (1, 2, ..., 10, много).
Мне кажется это уже детали. Можно переписать так:
template<unsigned I>
struct Q : Q<I-1> {};
template<>
struct Q<0> {};
unsigned const tuzemnaya_beskone4nost = 100;
void aaa(Q<0>) {}
void aaa(Q<1>) {}
void aaa(Q<2>) {}
int main()
{
aaa(Q<tuzemnaya_beskone4nost>());
}
Здравствуйте, Кодт, Вы писали:
К>Можно принять "туземную бесконечность" (1, 2, ..., 10, много).
а че это не компилится?
template <int N>
struct Inf
{ operator Inf<N-1>() {return Inf<N-1>();}
};
void InfFun(Inf<0>) {}
int main(int argc, char* argv[])
{ Inf<2> i2;
Inf<1> i1=i2;
Inf<0> i0=i1;
InfFun(Inf<2>()); // no suitable user-defined conversion from "Inf<2>" to "Inf<0>" exists
return 0;
}
Здравствуйте, Programador, Вы писали:
P>а че это не компилится?
P> InfFun(Inf<2>()); // no suitable user-defined conversion from "Inf<2>" to "Inf<0>" exists
По стандарту, допускается не более одного неявного действия из (static_cast и параметризация шаблона).
Неявный static_cast — это
— приведение вверх по иерархии
— пользовательский оператор приведения типа
— конструктор с одним параметром
В данном же случае нужно два действия: Inf<2>::operator Inf<1>() и Inf<1>::operator Inf<0>().
А вот построить иерархию — это пожалуйста. От любого потомка к любой базе — приведение делается одним махом.
... << RSDN@Home 1.2.0 alpha rev. 655>>