Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.72/25: Рейтинг темы: голосов - 25, средняя оценка - 4.72
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614

Как правильно работать с std::is_base_of?

19.06.2017, 21:14. Показов 4955. Ответов 36
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Объясните пожалуйста, почему такой код не работает?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <vector>
 
class A
{
    public:
};
class B : public A
{
    public:
};
class C : public A
{
    public:
};
 
class BAble : public B
{
    public:
};
class CAble : public C
{
    public:
};
 
std :: vector<B*> bv;
std :: vector<C*> cv;
 
template<class T>
void func( T* a )
{
  if( std::is_base_of<B,T> :: value )
    bv.push_back( a );
 
  if( std::is_base_of<C,T> :: value )
    cv.push_back( a );
}
 
 
int main()
{
    BAble* ba = new BAble;
    BAble* ba2 = new BAble;
    CAble* ca = new CAble;    
    
    func( ba );
    func( ba2 );
    func( ca );
}
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
19.06.2017, 21:14
Ответы с готовыми решениями:

Как правильно перевести std::wstring в std::string ?
Собственно как? :)

Как работать с отдельными элементами строки std::string?
как работать с отдельными элементами строки в c++, используя тип string?

Как правильно сделать std::string блоками по 16 байт?
Я новенькая, простите за плохое оформление. Есть строка std::string которую нужно поместить в блок по 16 байт. (для aes шифирования) ...

36
Эксперт С++
1624 / 954 / 782
Регистрация: 06.02.2016
Сообщений: 2,452
Записей в блоге: 31
20.06.2017, 18:08
Студворк — интернет-сервис помощи студентам
Bretbas, этот тип по умолчанию будет nullptr
0
495 / 209 / 70
Регистрация: 27.05.2016
Сообщений: 557
20.06.2017, 18:12
Это шаблонный параметр по умолчанию, типа если не задается явно, то это будет nullptr
C++
1
2
3
4
5
6
7
8
9
10
template <typename T, typename = int>
void foo()
{
    puts(__PRETTY_FUNCTION__);
}
 
int main()
{
    foo<double>();
}
1
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13207 / 6841 / 1823
Регистрация: 18.10.2014
Сообщений: 17,304
20.06.2017, 19:00
Цитата Сообщение от Peoples Посмотреть сообщение
Bretbas, этот тип по умолчанию будет nullptr
Тип не может быть nullptr. nullptr - это значение, а не тип. И в шаблоне там сидит параметр-значение, а не параметр-тип.
1
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
20.06.2017, 20:25  [ТС]
все равно не могу допетрить как это работает. Как он выбирает между двумя функциями, какую использовать:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    template<typename T, typename std::enable_if<std::is_base_of<RenderableSystem, T>::value, T>::type* = nullptr>
    T* addSystem()
    {
        T* system = new T();
        _renderableSystems.push_back( system );
        return system;
    }
 
    template<typename T, typename std :: enable_if<std :: is_base_of<LogicalSystem, T> :: value, T> :: type* = nullptr>
    T* addSystem()
    {
        T* system = new T();
        _logicalSystems.push_back( system );
        return system;
    }
Добавлено через 7 минут
точнее примерно понимаю...
запись typename std::enable_if<std::is_base_of<RenderableSystem, T>::value, T>::type* = nullptr
задает шаблонный параметр с типом T, в том случае, если T наследник RenderableSystem, и задает этому параметру-значение nullptr? Или как?
В чем разница между такой записью?
C++
1
2
3
4
5
6
7
    template<typename T, typename = std :: enable_if<std :: is_base_of<RenderableSystem, T> :: value, T>::type>
    T* addSystem()
    {
        T* system = new T();
        _renderableSystems.push_back( system );
        return system;
    }
0
What a waste!
 Аватар для gray_fox
1612 / 1304 / 180
Регистрация: 21.04.2012
Сообщений: 2,735
20.06.2017, 21:49
Цитата Сообщение от Bretbas Посмотреть сообщение
В чем разница между такой записью?
Хороший вопрос)

Вот что пишут по этому поводу на (stackoverflow):
Default template arguments are not part of the signature of a template (so both definitions try to define the same template twice). Their parameter types are part of the signature, however.
Т.е., т.к. аргументы шаблона функции не являются частью его сигнатуры, в первом случае объявляется один и тот же шаблон функции:
C++
1
2
3
4
5
template<typename, typename>
T* addSystem();
 
template<typename, typename>
T* addSystem();
Во втором случае параметры шаблона различны:
C++
1
2
3
4
5
template<typename, typename std::enable_if<std::is_base_of<LogicalSystem, T>::value>::type>
T* addSystem();
 
template<typename, typename std::enable_if<std::is_base_of<RenderableSystem, T>::value>::type>
T* addSystem();
Теперь осталось только добавить аргумент по умолчанию для второго параметра, что бы явно его не указывать. Т.к. std::enable_if<...>::type по умолчанию - void, то можно использовать указатель на void и нулевой указательr:
C++
1
typename std::enable_if</* ... */>::type * = nullptr
P.S: не гарантирую, что всё, что я написал, абсолютно верно)
1
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13207 / 6841 / 1823
Регистрация: 18.10.2014
Сообщений: 17,304
20.06.2017, 21:52
Цитата Сообщение от Bretbas Посмотреть сообщение
задает шаблонный параметр с типом T, в том случае, если T наследник RenderableSystem, и задает этому параметру-значение nullptr?
А * кто потерял? Это нетиповой шаблонный параметр типа T * с умолчательным значением nullptr.
1
What a waste!
 Аватар для gray_fox
1612 / 1304 / 180
Регистрация: 21.04.2012
Сообщений: 2,735
20.06.2017, 22:04
Bretbas, можно, опять же, воспользоваться простой перегрузкой, если enable_if смущает:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class SystemManager
{
public:
    template<typename T>
    T* addSystem()
    {
        T* system = new T();
        _addSystem(system);
        return system;
    }
 
private:
    void _addSystem(RenderableSystem* system)
    {
        _renderableSystems.push_back(system);
    }
    
    void _addSystem(LogicalSystem* system)
    {
        _logicalSystems.push_back(system);
    }
 
    // ...
};
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
21.06.2017, 16:26  [ТС]
gray_fox,
Цитата Сообщение от gray_fox Посмотреть сообщение
Во втором случае параметры шаблона различны:
Цитата Сообщение от gray_fox Посмотреть сообщение
C++
1
2
3
4
template<typename, typename std::enable_if<std::is_base_of<LogicalSystem, T>::value>::type>
T* addSystem();
template<typename, typename std::enable_if<std::is_base_of<RenderableSystem, T>::value>::type>
T* addSystem();
И в чем разница этих двух функций? Так как аргументы шаблона не являются частью сигнатуры функции, то по идее эти две функции тоже одинаковые.

Цитата Сообщение от gray_fox Посмотреть сообщение
Теперь осталось только добавить аргумент по умолчанию для второго параметра, что бы явно его не указывать. Т.к. std::enable_if<...>::type по умолчанию - void, то можно использовать указатель на void и нулевой указатель
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Это нетиповой шаблонный параметр типа T * с умолчательным значением nullptr.
Это понял. Спасибо

Цитата Сообщение от gray_fox Посмотреть сообщение
можно, опять же, воспользоваться простой перегрузкой, если enable_if смущает
Так будет не очень элегантно выглядеть, ибо на стадии компиляции нельзя будет проверить T является наследником System, или это другой тип, не относящийся вообще к этому всему
0
What a waste!
 Аватар для gray_fox
1612 / 1304 / 180
Регистрация: 21.04.2012
Сообщений: 2,735
21.06.2017, 16:34
Цитата Сообщение от Bretbas Посмотреть сообщение
И в чем разница этих двух функций?
Типы 2-го параметра шаблона разные (нетипового).
Цитата Сообщение от Bretbas Посмотреть сообщение
Так будет не очень элегантно выглядеть, ибо на стадии компиляции нельзя будет проверить T является наследником System, или это другой тип, не относящийся вообще к этому всему
Оно и так и так не скопилируется, если T не наследник {Logical/Renderable}System, что с enalbe_if, что без, с аналогичными сообщениями об ошибке. Если хочешь добавить проверку, то лучше добавь static_assert.
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
21.06.2017, 17:12  [ТС]
gray_fox,
Типы 2-го параметра шаблона разные (нетипового).
std::enable_if объявляет тип type равный T в том случае, если первый параметр шаблона true.
Возьмем снова эти две функции:
C++
1
2
3
4
template<typename T, typename std::enable_if<std::is_base_of<LogicalSystem, T>::value>::type>
T* addSystem();
template<typename T, typename std::enable_if<std::is_base_of<RenderableSystem, T>::value>::type>
T* addSystem();
Допустим T = PhysicsSystem, который наследуется от LogicalSystem.
Берем первую функцию:
C++
1
2
template<typename T, typename std::enable_if<std::is_base_of<LogicalSystem, T>::value>::type>
T* addSystem();
и подставляем PhysicsSystem
C++
1
2
template<PhysicsSystem, typename std::enable_if<std::is_base_of<LogicalSystem, PhysicsSystem>::value>::type>
PhysicsSystem* addSystem();
в данном случае std::enable_if<std::is_base_of<LogicalSystem, PhysicsSystem>::value>::type будет иметь тип PhysicsSystem?
Вот второй функции второго параметра шаблона вообще, я так понимаю не будет, так как std::enable_if<std::is_base_of<RenderableSystem, T>::value>::type не выведется?
Тогда вторая функция будет для PhysicsSystem иметь вид просто:
C++
1
2
template<PhysicsSystem>
PhysicsSystem* addSystem();
У меня сейчас голова вскипит
0
What a waste!
 Аватар для gray_fox
1612 / 1304 / 180
Регистрация: 21.04.2012
Сообщений: 2,735
21.06.2017, 17:41
Цитата Сообщение от Bretbas Посмотреть сообщение
Допустим T = PhysicsSystem, который наследуется от LogicalSystem.
Берем первую функцию:
C++
1
2
template<typename T, typename std::enable_if<std::is_base_of<LogicalSystem, T>::value>::type>
T* addSystem();
и подставляем PhysicsSystem
C++
1
2
template<PhysicsSystem, typename std::enable_if<std::is_base_of<LogicalSystem, PhysicsSystem>::value>::type>
PhysicsSystem* addSystem();
в данном случае std::enable_if<std::is_base_of<LogicalSy stem, PhysicsSystem>::value>::type будет иметь тип PhysicsSystem?
Нет, будет void. 2-й параметр шаблона enable_if - void по умолчанию. Он и используется в качестве члена type.

Добавлено через 2 минуты
Цитата Сообщение от Bretbas Посмотреть сообщение
Вот второй функции второго параметра шаблона вообще, я так понимаю не будет
Будет ошибка во время инстанциирования шаблона (так как type в enable_if не будет) и он будет отброшен как неподходящий кандидат.
1
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
21.06.2017, 18:28  [ТС]
gray_fox, хорошо...вроде бы понял. Тогда я не понимаю теперь вот эту запись:
C++
1
2
3
4
template<typename T, typename = std :: enable_if<std :: is_base_of<RenderableSystem, T> :: value, T>::type>
T* addSystem()
{
}
Зачем нужно = перед вторым typename
0
Эксперт С++
1624 / 954 / 782
Регистрация: 06.02.2016
Сообщений: 2,452
Записей в блоге: 31
21.06.2017, 18:30
Bretbas, Значение по умолчанию
1
What a waste!
 Аватар для gray_fox
1612 / 1304 / 180
Регистрация: 21.04.2012
Сообщений: 2,735
21.06.2017, 18:31
Bretbas, во-первых, typename потерял. Должно быть:
C++
1
typename = typename std :: enable_if<std :: is_base_of<RenderableSystem, T> :: value, T>::type
type тут зависимый (от параметров шаблона) тип.

Тут у шаблона 2 параметра, у 2-го есть параметр по умочанию.
1
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
21.06.2017, 18:52  [ТС]
gray_fox, итак подведем итоги.
Запись
C++
1
2
template<typename T, typename std::enable_if<std::is_base_of<LogicalSystem, T>::value>::type>
T* addSystem();
параметризует второй параметр шаблона как void в том случае, если T наследует от LogicalSystem

C++
1
2
template<typename T, typename K = typename std :: enable_if<std :: is_base_of<RenderableSystem, T> :: value, T>::type>
T* addSystem();
параметризует второй параметр шаблона как к примеру K и делает у него значение по умолчанию void если T наследует от RenderableSystem

Так?
0
What a waste!
 Аватар для gray_fox
1612 / 1304 / 180
Регистрация: 21.04.2012
Сообщений: 2,735
21.06.2017, 19:00
Цитата Сообщение от Bretbas Посмотреть сообщение
Запись
C++
1
2
template<typename T, typename std::enable_if<std::is_base_of<LogicalSystem, T>::value>::type>
T* addSystem();
параметризует второй параметр шаблона как void в том случае, если T наследует от LogicalSystem
2-й параметр будет нетиповым параметром шаблона типа void, если T наследует от LogicalSystem. Т.е. в итоге, при удачном инстанциировании, получаем:
C++
1
T* addSystem<T, void>();
(Что, само по себе, не имеет смысла, т.к. нет значения, которое можно было бы передать как 2-й параметр).
Цитата Сообщение от Bretbas Посмотреть сообщение
C++
1
2
template<typename T, typename K = typename std :: enable_if<std :: is_base_of<RenderableSystem, T> :: value, T>::type>
T* addSystem();
параметризует второй параметр шаблона как к примеру K и делает у него значение по умолчанию void если T наследует от RenderableSystem
Не понял "параметризует второй параметр шаблона как к примеру K". Тут 2-й параметр шаблона "типовой" с умолчательным значением. Нет, будет T, т.к. явно указан T. K == T.
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
21.06.2017, 19:02  [ТС]
Ура Я догнал наконец
Спасибо всем, кто помогал gray_fox, тебе особенно, за то что возился со мной

Все-таки шаблоны - это крутая штука
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
21.06.2017, 19:02

Как правильно дать имена элемментам std::pair
Добрый день, typedef int Bar; typedef std::pair&lt;Foo*, Bar&gt; A; typedef...

Std::set с кастомным классом, как правильно перегрузить оператор < ?
Доброго времени суток, у меня имееться такой класс: class Truck { public: size_t getNumber(); Truck() =...

Is_base_of
Продолжаем день странных вопросов: Вот реализация is_base_of: //is_base_of &lt;A,B&gt; Узнаёт, является ли B наследником A typedef char...

Как правильно работать с vector?
// Create buttons. int const size = 5; int x = 50; int y = 50; int j = 0; vector&lt;Button*&gt; vLevel; for (int i = 0; i &lt;...

Как правильно работать со строками?
Вообщем суть вопроса такова, что я не совсем понимаю как происходит работа со строками. Вот к примеру: есть входной файл a.in в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
37
Ответ Создать тему
Новые блоги и статьи
28. КОнкретное развертывание плана номер 1 из поста номер 27
anaschu 22.06.2026
Можно ли из модели получить конкретные строительные требования? Честно — напрямую из текущей модели такие ответы не получить. Но цепочка логики есть, и она не такая длинная. Где разрыв . . .
27. Планы на разработку функциональных требований к строительству внутри модели пищеблока (или не только его?)
anaschu 22.06.2026
Что уже реализовано и даёт конфликты «бесплатно» Самый простой конфликт уже работает — конфликт за ресурс-работника. Заданий больше, чем доступных поваров → очередь в queue1. Это прямое отражение. . .
26. мед мат модель.Какие типы конфликтов функциональных требований можно рассчитать через ДЕС-моделирование (СМО) в AnyLogic?
anaschu 22.06.2026
Что ДЕС/ СМО умеет считать напрямую: Конфликты за ресурсы (очереди, узкие места). Несколько типов агентов (повара, учителя, рабочие, пациенты) претендуют на один ресурс (лифт, вход, коридор,. . .
25 модель здравосохранения и функциональных требований к пищеблоку: конфликты функциональных требований.
anaschu 22.06.2026
Есть ли данные о том, какие функциональные/ эксплуатационные требования или их сочетания труднее всего учитывать при проектировании зданий? Да, такие данные есть, и они хорошо описаны и в российской,. . .
Remote Connection Manager
DevAlt 21.06.2026
Написал для себя небольшую прилагу: https:/ / github. com/ altbodhi/ ReConMan По итогу пришел к мысли, что DU не дружат с существующими технологиями. От сериализации до отображения в реляционную. . .
Администрация Хабра удаляет новые энрегоэфективные алгоритмы, которые не западной школы кода, и вовсе никак не сгенерировавны.
Hrethgir 20.06.2026
Делается это, как замечено, при правках - при объявлении концептуальных отличий в алгоримах. Делается это, по линейке событий - после дополнения публикации основными отличиями от основных западных. . .
Процесс ориентированная диалектика (не новость - просто системное обновление, философия).
Hrethgir 20.06.2026
Однажды один участник в своём блоге, на этом форуме, сделал запись "О языках замолвите слово". Понимая, что язык - важная вещь, я решил хорошо подумать, прежде чем сказать, и сказал то, что вы видите. . .
Контроль уникальности строк в табличной части документа
Maks 18.06.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ПланированиеСпецтехники" с табличной частью "НаличиеОборудования", разработанного в КА2. Задача: контроль уникальности строк в. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru