LINUX.ORG.RU

Alexandescu Modern C++... длинное название: странное противоречие

 ,


0

2

Странное противоречие. Написанное на странице 92 (класс Functor) о том, что template class’ы с тем же названием не могут иметь разное количество template параметров противоречит коду на странице 57 (класс GenScatterHierarchy) и 60 (класс FieldHelper). Если не хотите не обращайте пожалуйста внимание на количество кода а на количество template параметров. Например тут их явно разное количество и это не специализация шаблона:

// Pass an atomic type (non-typelist) to Unit
template <class AtomicType, template <class> class Unit>
class GenScatterHierarchy : public Unit<AtomicType>
{
typedef Unit<AtomicType> LeftBase;
};
// Do nothing for NullType
template <template <class> class Unit>
class GenScatterHierarchy<NullType, Unit>
{
};

А на странице 92 о классе Functor написано, что так нельзя. Я, конечно, могу сам это все компилировать и проверять, но я не настолько хорошо знаю шаблоны. Может есть какая-то тонкость?

Страница 92:

Even after making this decision, life is not a lot easier. C++ does not allow templates with the same name and different numbers of parameters. That is, the following code is invalid:

// Functor with no arguments
template <typename ResultType>
class Functor
{
...
};
// Functor with one argument
template <typename ResultType, typename Parm1>
class Functor
{
...
};

С другой стороны страница 57:

template <class TList, template <class> class Unit>
class GenScatterHierarchy;
// GenScatterHierarchy specialization: Typelist to Unit
template <class T1, class T2, template <class> class Unit>
class GenScatterHierarchy<Typelist<T1, T2>, Unit>
: public GenScatterHierarchy<T1, Unit>
, public GenScatterHierarchy<T2, Unit>
{
public:
typedef Typelist<T1, T2> TList;
typedef GenScatterHierarchy<T1, Unit> LeftBase;
typedef GenScatterHierarchy<T2, Unit> RightBase;
};
// Pass an atomic type (non-typelist) to Unit
template <class AtomicType, template <class> class Unit>
class GenScatterHierarchy : public Unit<AtomicType>
{
typedef Unit<AtomicType> LeftBase;
};
// Do nothing for NullType
template <template <class> class Unit>
class GenScatterHierarchy<NullType, Unit>
{
};

Или страница 60:

template <class H, typename R>
inline R& FieldHelper(H& obj, Type2Type<R>, Int2Type<0>)
{
typename H::LeftBase& subobj = obj;
return subobj;
}
template <class H, typename R, int i>
inline R& FieldHelper(H& obj, Type2Type<R> tt, Int2Type<i>)
{
typename H::RightBase& subobj = obj;
return FieldHelper(subobj, tt, Int2Type<i- 1>());
}
//Refer to HierarchyGenerators.h for FieldTraits' definition
template <int i, class H>
typename Private::FieldTraits<H>::At<i>::Result&
Field(H& obj)
{
typedef typename Private::FieldTraits<H>::At<i>::Result
Result;
return FieldHelper(obj, Type2Type<Result>(), Int2type<i>());
}

Тут, например, опять разное количество template параметров:

template <class H, typename R>
inline R& FieldHelper(H& obj, Type2Type<R>, Int2Type<0>)
{
typename H::LeftBase& subobj = obj;
return subobj;
}
template <class H, typename R, int i>
inline R& FieldHelper(H& obj, Type2Type<R> tt, Int2Type<i>)
{
typename H::RightBase& subobj = obj;
return FieldHelper(subobj, tt, Int2Type<i- 1>());
}
★★

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

могут класс иметь разное количество параметров.

Даже произвольное.

Просто вспомни класс варинт

std::variant<int, long, double, std::string>;
std::variant<int, long>;
fsb4000 ★★★★★
()
Ответ на: комментарий от fsb4000

т.е. это ошибка со стороны Alexandrescu?

Even after making this decision, life is not a lot easier. C++ does not allow templates with the same name and different numbers of parameters. That is, the following code is invalid:

Я уже замечал ошибки в его книге, но они были мелкие, а это какой-то facepalm.

dissident ★★
() автор топика
Ответ на: т.е. это ошибка со стороны Alexandrescu? от dissident

variant использует variadic templates

PS variant, кажется, появился когда появились variadic templates, а книга написана до этого! Могу, правда, ошибаться.

PS Книга вот эта: https://www.amazon.com/Modern-Design-Generic-Programming-Patterns/dp/0201704315. Написана в 2001 если верить https://en.wikipedia.org/wiki/Modern_C%2B%2B_Design. Variadic templates тогда не было.

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

там речь о с++14

Allows customizing class and variable (since C++14) templates for a given category of template arguments. 

И далее:

and declarator identifies the name of a previously declared variable template . (since C++14)

А это более старый код (книга написана в 2001):

template <class H, typename R>
inline R& FieldHelper(H& obj, Type2Type<R>, Int2Type<0>)
{
...
}
template <class H, typename R, int i>
inline R& FieldHelper(H& obj, Type2Type<R> tt, Int2Type<i>)
{
...
}

C другой стороны на странице 92 он пишет:

Even after making this decision, life is not a lot easier. C++ does not allow templates with the same name and different numbers of parameters. That is, the following code is invalid:
// Functor with no arguments
template <typename ResultType>
class Functor
{
...
};
// Functor with one argument
template <typename ResultType, typename Parm1>
class Functor
{
...
};

Или сам себе противоречит иои я туплю.

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

А! да! поэтому Type2Type ему нужен. последний (надеюсь) вопрос можно?

Вот это:

// Pass an atomic type (non-typelist) to Unit
template <class AtomicType, template <class> class Unit>
class GenScatterHierarchy : public Unit<AtomicType>
{
typedef Unit<AtomicType> LeftBase;
};
// Do nothing for NullType
template <template <class> class Unit>
class GenScatterHierarchy<NullType, Unit>
{
};

Это просто разные классы из-за того, что один наследует от Unit, а другой нет? Можешь потвердить? Если это так, то «все мне ясно стало теперь»

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

Не. Это один класс.

Мы пишем сначала самую общую версию.

template <class AtomicType, template <class> class Unit>
class GenScatterHierarchy : public Unit<AtomicType>
{
typedef Unit<AtomicType> LeftBase;
};

Потом пишем, что-то более специфичное(Когда первый параметр не любой, а Nulltype)

// Do nothing for NullType
template <template <class> class Unit>
class GenScatterHierarchy<NullType, Unit>
{
};

А компилятор сначала проверяет более специфичные вещи, потом идёт к общему.

Почитай https://en.cppreference.com/w/cpp/language/partial_specialization

Просто не читай то что выделено зеленым и подписано since C++14.

Там просто сразу для всех версий пишут.

Примеры оттуда может помогут лучше понять…

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

спасибо!

Кажется я поверхностно понял. Просто мое знание C++ до сих пор огранивалось до наследования и такого рода вещей. Если я правильно поверхностно понял то:

  • Во первых я забыл, что template function (где нет partial specialization, почему и нужен Type2Type, чтобы эмулировать partial specialization overload’ом (впрочем это не по теме)) и template class (где partial specialization есть) - это разные вещи
  • Во вторых я так понимаю, что template functions с тем же самым названием могут иметь любое количество template параметров (причем разное в разных template функциях, причем с тем же названием) - прошу поправить если это не так
  • В третьих я перепутал partial specialization класса («уменьшение» template параметров, вернее скорее приравнивание их друг к другу) с созданием класса с тем же именем, но позже (в смысле в файле позже) и с большим количеством параметров, что невозможно без variadic templates - опять же прошу поправить меня если это не так

PS Я понимаю, что читаю о старой версии C++, но б… как же можно было так заморочить язык. :-\

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

еще раз спасибо!

Я этого Александреску уже несколько лет собирался прочитать и все не было времени. А без тебя сидел бы над этими двумя разделами еще неделю.

dissident ★★
() автор топика
Ответ на: спасибо! от dissident

с созданием класса с тем же именем, но позже (в смысле в файле позже) и с большим количеством параметров, что невозможно без variadic templates

Ну вообще всякая магия существует, есть же boost::variant для C++98, но там магия на препроцессоре…

Проще думать что нельзя и пользоваться новыми стандартами и компиляторами.

fsb4000 ★★★★★
()
Ответ на: спасибо! от dissident

Во вторых я так понимаю, что template functions с тем же самым названием могут иметь любое количество template параметров (причем разное в разных template функциях, причем с тем же названием)

вот кстати пример такой функции:

https://en.cppreference.com/w/cpp/algorithm/transform_reduce

от 3 до 6 шаблонных параметров

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

Если уже цепляться к словам то последнее GenScatterHierarchy это не шаблон класса, а специализация шаблона класса. Но главное то, что с большего все стало понятно.

dissident ★★
() автор топика
Ответ на: спасибо! от dissident

В 03 тоже можно было разное число аргументов у шаблонов иметь, так что, всё-таки, опечатка. Либо какой-то совсем дремучий стандарт.

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

Ясно, что устарел. Как и Вирт со своими алгоритмами и данными. Но часть его идей я вижу в новых крестах. Хорошо знать, откуда у этого г… ноги растут. Кроме того, несмотря на новые фреймворки и языки мало что меняется. Ну разве что кроме статистики (я имею ввиду AI).

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

В 03 тоже можно было разное число аргументов у шаблонов иметь, так что, всё-таки, опечатка. Либо какой-то совсем дремучий стандарт.

У шаблонов фунций или шаблонов классов? Если верить педивикии. то книга написана в 2001 году: https://en.wikipedia.org/wiki/Modern_C%2B%2B_Design. Если же верить книге, то в том дремучем году шаблоны функций с одинаковыми именами могли (и далее могут) иметь разное количество template параметров. Шаблоны классов же нет. И до сих пор, похоже, не могли бы если бы не variadic templates, которых тогда не было.

Бардак у меня в голове возник из-за того, что я перепутал специализацию шаблона класса (который может иметь меньшее количество template параметров (тем самым декларируя, например, что T1 это тоже самое. что T2) с шаблоном класса но fsb4000 вставил мне мозги.

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

Я к тому, что языковые возможности с конца 90хх были довольно неплохо так расширены и часть той акробатики, что выделывал тов. Александреску, сейчас просто не нужна за имением variadic templates, parameter packs, decltype, constexpr, etc

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

А я к тому, что то, что появилось в новом С++ берет свое начало у Коплиена, Александреску и им прочим. Сравни например typelists и tuples. «Не зная историю мы будем вынуждены вечно ее повторять».

PS Я видел на каком-то из новых крестов такой перемороченный маразм, что лучше бы он был написан на «C с классами». Кроме того эти нововведения сделаны скорее всего акробатикой описаной еще в 90 годы. Ну и читая румына понимаешь, что template’ы не кусают, просто некоторые пишут это слово где попало, чтобы показать, что они его знают. Как в «Записках офицера красной армии», где крестьянин, ставший вдруг офицером и сняв в Вильно комнату долго не мог понять как пользоваться кранами в ванной, а когда наконец понял и помылся, то специально оставил всю ванную грязной воды, чтобы хозяйки поняли, какой он знающий человек и как умеет пользоваться ванной.

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

Если же верить книге, то в том дремучем году шаблоны функций с одинаковыми именами могли (и далее могут) иметь разное количество template параметров. Шаблоны классов же нет. И до сих пор, похоже, не могли бы если бы не variadic templates

template parameter pack это один параметр.

Бардак у меня в голове возник из-за того, что я перепутал специализацию шаблона класса (который может иметь меньшее количество template параметров

А может и большее.

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

У тебя аргументы, а не параметры.

Можешь развинуть мысль помня о том, что книга написана в 2001 году? Как я понял и тогда и сейчас шаблоны функций с одинаковым именем могут иметь любое количество параметров шаблона. А вот шаблоны класс (я не имею ввиду специалиацию) до появления variadic temlates не могли.

Т.е так было без акробатики нельзя:

template<class T1>
class X {
[skip]
}

template<class T1, class T2>
class X {
[skip]
}

Или речь лишь о том, что в

template<class T>
class X {
[skip]
}

T правильно называть аргументом а не параметром?

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

https://en.cppreference.com/w/cpp/language/template_parameters

Так какое сообщение с этой оговоркой fsb4000 ты имел ввиду? Я действительно пытаюсь разобраться правильно ли я понял румына и fsb4000 просто перепутал термины или я совсем в лесу (https://youtu.be/7uUECUTvaK8)

Спасибо с горы!

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

Т.е. речь всего лишь об ошибке next_time:

В 03 тоже можно было разное число аргументов у шаблонов иметь, так что, всё-таки, опечатка. Либо какой-то совсем дремучий стандарт.

? В дискуссии это слово выступает только здесь если я правильно грепаю фаерфоксом.

Остальное по сути верно?

Или же речь о том. что последний GenScatterHierarchy - это специализация шаблона класса GenScatterHierarchy с NullType аргументом (а не шаблон класса с другим параметром, но тем же назварием)? Если речь об этом. то мы же уже, кажется, пришли к согласию. что что это так.

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

Это не специализации одного шаблона, это просто разные шаблоны функций с одним и тем же именем, т.е. шаблоны оверлоадов.

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

Как я понял и тогда и сейчас шаблоны функций с одинаковым именем могут иметь любое количество параметров шаблона. А вот шаблоны класс (я не имею ввиду специалиацию) до появления variadic temlates не могли.

И после появления не могут. Я уже писал, что parameter pack это один параметр.

A template parameter pack is a template parameter that accepts zero or more template arguments.

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

Это не специализации одного шаблона, это просто разные шаблоны функций с одним и тем же именем, т.е. шаблоны оверлоадов.

Понял. Слова «шаблоны оверлоадов» прояснили в голове спасибо.

Правда изначально речь шла о шаблонах классов, а не функций:

Even after making this decision, life is not a lot easier. C++ does not allow templates with the same name and different numbers of parameters.

(с) румын в 2001 году (полная цитата в первом сообщении).

PS Я ответы на свои вопросы уже вроде как получил (разве что они были ошибочными).

PPS За формулировку «шаблоны оверлоадов» и информацию о temlate parameer pack еще раз спасибо.

dissident ★★
() автор топика
Последнее исправление: dissident (всего исправлений: 2)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.