ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Воскресенье
22 декабря
1015382 Топик полностью
Связанные сообщения
Cpp
Мнится мне, что кто-то уже записывал такие мысли на песках Сахары...2024-06-19
Вы просто не умеете его готовить. Я бы мог бесконечно показывать примеры, но это непробиваемо. Сразу авторитетно докажут, что у ...2022-09-30
Embedded Template Library (iar arm 9.20.4)2022-05-18
Наброшу.2021-12-06
В C++ доступна вся C-библиотека. Когда C++ сам себе разумеется нет, а как ты себе представляешь? Можешь написать свою реализацию...2020-09-23
Ты хочешь static_if, которого в C++ в чистом виде нет. constexpr if это совсем не то, т.к. он неизбежно будет компилиров...2020-07-02
Надо понимать, что класс -- это не структура. Применительно к C++ мне больше нравится слово тип. Тип -- это сущность существующа...2020-04-26
Я говорю про другую типизацию. Не про int или long, и даже не про int или char*. Программа на ООП-языке существует в рамкой неко...2019-12-19
C#, Java и тем более Javascript -- это совсем другой код, нежели C++. На порядок менее оптимальный, если конечно задача не своди...2019-12-19
С языком очень даже связано. Компилирующие языки со статической типизацией (C++, C#, Java, C, Pascal) пропускают гораздо меньше ...2019-12-17
Не совсем. C++ -- это уход в сторону _типизированных_ ЯВУ, а Java или C# -- подвижка в сторону "управляемого кода" и что наиболе...2019-11-03
Да конечно, ну вот расскажи, как оно работает -->2019-10-25
Мне какой-то куб для Renesas вспомнился, лет 6 тому назад. Они хвалились, что у них код компилится сразу, как его пишешь. В итог...2019-10-25
Увы, часто нет. Ардуины не просто так возникли. МК подросли и стали возможны другие подходы к разработке. Видно же что делается:...2019-03-03
Не соглашусь, во-первых я чётко подвёл к мысли, что возможны разные классификации, существование одних не запрещает другие. И ес...2019-03-03
С этого стоило и начинать. С того, что язык скриптовый. И это уводит совсем в другую сторону, практически в параллельную вселенн...2019-03-01
EvgenyCD! Смотри ссылку! Я понял, что это круче чем swig, например, в определённых обстоятельствах. Правда руки применять надо...2017-02-09
fk0, легенда (02.07.2020 15:23, просмотров: 982) ответил йцyкeн на Как в C++ узнать, имеет ли класс функцию с определённым именем? Задача такая: есть шаблон функции, параметром является класс из некоторой группы. Все классы этой группы имеют функцию f(), но некоторые имеют более продвинутую функцию super_f(). Хочется вызывать super_f(), если она есть, а если нет, вызывать обычную f().
В общем случае может быть 2-3 подхода перечисленных ниже. В базе всегда SFINAE -- шаблон откидывается и просматриваются следующие, если тип в шаблоне не может быть выведен. Сегодня, при использовании C++17, можно использовать идиому void_t (см. на cppreference.com) для того, чтобы написать шаблон типа раскрывающийся по-разному (true/false) если для его параметра можно или нельзя определить возвращаемое значение искомой функции (через decltype) которая как будто 

присутствует (через declval) и далее с помощью enable_if выбрать шаблон.


В C++14 нет void_t но его можно самому определить (как -- описано на cppreference.com). В C++11 нет std::declval ("как будто есть тип"), но он заменяется на static_cast<T*>(0) во всех почти случаях.


Вместо того, чтоб расписывать enable_if(одно) и enable_if(!одно-а-другое), можно ввести понятие "приоритета" шаблонной функции и выбирать их по приоритету, через функцию-диспетчер. Как -- показано в моём примере, который для C++11. Там же избавились от declval, но остались с decltype, который принципиально необходим. Кстати там же показано, что от enable_if иногда можно избавиться. Ведь компилятору нужен не enable_if, а лишь факт (не)выводимости типа.


В C++03 ситуация намного хуже, так как там нет decltype. Это принципиальная проблема, и приходится выкручиваться через sizeof(), который работает так же, но возвращает не тип, а размер. Ну а размер может оказаться разный, в зависимости от того как раскроется шаблон структуры применённый к типу. В итоге информацию о типе извлечь можно, но только в виде числа, а не типа, и так закодировано может быть ограниченное множество типов. Но для выбора да/нет вполне годится.



#include <stdio.h>

struct A
{
void f() { puts("f"); }
};

struct B : public A
{
void super_f() { puts("super_f"); }
};

#if 0 // C++17 (C++14 if you write own std::void_t), in C++11 you also need to write own std::declval

#include <type_traits>
#include <utility>

#if 0// variant which requires std::void_t
template <typename, typename = void> struct HasSuperF : std::false_type {};
template <typename T> struct HasSuperF<T, std::void_t<decltype(std::declval<T>().super_f())> > : std::true_type {};

template <typename T>
typename std::enable_if<! HasSuperF<T>::value, void>::type test(T v)
{
v.f();
}

template <typename T>
typename std::enable_if<HasSuperF<T>::value, void>::type test(T v)
{
v.super_f();
}

#else// other C++11 variant

template <int Order> struct Priority : Priority<Order - 1> {};
template <> struct Priority<0> {};

template <typename T>
void _test(T v, Priority<0>)
{
v.f();
}

template <typename T>
decltype(void(static_cast<T*>(0)->super_f())) _test(T v, Priority<1>)
{
v.super_f();
}

template <typename T>
void test(T v) { _test(v, Priority<1>()); }

#endif

#else// C++03

template <class Class>
struct HasSuperF
{
private:
template <typename T, T> struct equal_types;

template <typename> static int check(...);

template <typename C> static char check(equal_types<void (C::*)() const, &C::super_f> *);
template <typename C> static char check(equal_types<void (C::*)(), &C::super_f> *);

public:
static bool const value = sizeof(check<Class>(0)) == sizeof(char);
};

template <bool, typename> struct EnableIf;
template <typename T> struct EnableIf<true, T> { typedef T type; };

template <class T>
typename EnableIf<! HasSuperF<T>::value, void>::type test(T v)
{
v.f();
}

template <class T>
typename EnableIf<HasSuperF<T>::value, void>::type test(T v)
{
v.super_f();
}

#endif
int main()
{
test(A());
test(B());
return 0;
}

http://coliru.stacked-crooked.com/a/99da17f3635144bc

[ZX]