Иногда мы делаем вещи, ценность которых является весьма сомнительной. Это как раз тот самый случай.
Код лучше тысячи слов
Не буду тянуть кота за хвост, а перейду сразу к делу. Обычно мы используем CRTP примерно так:
template<typename type, typename tag>
struct Base
{};
template<typename type, typename tag>
void f(const Base<type, tag>&)
{}
struct Foo : Base<Foo, void>
{};
int main()
{
Foo foo;
f(foo);
}
Функции f()
на самом деле всё равно, какой тэг у её аргумента, и она принимает объект любого типа, унаследованого от Base
. Но не будет ли более удобным, если мы просто опустим не интересующий нас тэг? Зацените:
template<typename t>
struct base_tag { typedef decltype(get_tag((t*)42)) type; };
template<typename type,
typename tag = typename base_tag<type>::type>
struct Base
{
friend tag get_tag(type*); //never defined
};
template<typename type>
void f(const Base<type>&)
{}
struct Foo : Base<Foo, void>
{};
int main()
{
Foo foo;
f(foo);
}