Скомбинировать шаблоны и дефайны

Возвращаясь к теме ветки - почитал про про SFINAE, нашел некое костыльное решение…
Условную специализацию шаблона в зависимости от значения нон-типизованного параметра можно сделать вот так:

template <int A, typename=void>
class Foo {
    char* arr;
};

template <int A>
class Foo<A, std::enable_if_t<  A > 3 >>
{
    char arr[A];
};

может и не красиво, зато С++17 не нужен, в СТМ32-arduino с древним gcc arm-eabi собирается

Приятно всё-таки, что ТС не ньюфаг и всё понимает. Щас бы началось:

Папрашу не флудить! У миня тут " nervus rerum" - правильный код с видео, а камилятор ругаеца патаму что ардуина китайская! А вы тут са сваими нагами девачик! Не можите памочь, прахадите мима!

Как уже задоблали эти истерички!

1 лайк

куда спешить, дарагой?
Я и твою девочку посмотрел (аж в 4х вариантах), а потом и других… и код никуда не убежал :slight_smile:

Подсел типа :slight_smile:

В продолжение разговора про шаблоны, constexpr и поддержку С++17 в ардуино.
Вот этот код требует для своей компиляции всего лишь С++14:

template <int A, typename=void>
class Foo {
    char* arr;
};

template <int A>
class Foo<A, std::enable_if_t<  A > 3 >>
{
    char arr[A];
};

Однако на компиляторе arm-eabi для Ардуино Дуе не проходит и он. На компиляторе из комплекта RP2040 код собирается. Казалось бы, можно вставить в код директиву условной компиляции, чтобы для компиляторов, соответствующих стандарту С++14, выбирался этот код, а для более старых - другой.
Стандартный макрос для определения подмножества языка - это __cplusplus. Его значения должны быть:

199711L (C++98 or C++03)
201103L (C++11)
201402L (C++14)
201703L (C++17)
202002L (C++20)

Однако даже для аддона RP2040, который по факту соответвует С++14, макрос установлен в 199711L.
Ну как так то?!!!

а вы говорите в ардуино есть с++17…Может в каких-то отдельных случаях, после недельного допиливания напильником и есть, а в среднем, так сказать “из коробки” - НЕТУ!

можно на еще более древних плюсах это за счет специализаций сделать:

#include <iostream>

template <int A, bool B = (A > 3) >
struct Foo {
  static void f()
  {
    std::cout << "1111: A = " << A << "; A <= 3" << std::endl;
  }
};

template <int A>
struct Foo<A, true>
{
  static void f()
  {
    std::cout << "2222: A = " << A << "; A > 3" << std::endl;
  }
};


template <int A>
struct Bar
{
  static void f()
  {
    fImpl<(A > 3)>();
  }

private:
  template <bool B>
  static void fImpl()
  {
    std::cout << "A = " << A << "  fImpl<false>" << std::endl;
  }

  template <>
  static void fImpl<true>()
  {
    std::cout << "A = " << A << "  fImpl<true>" << std::endl;
  }
};


int main()
{
  Foo<3>::f();
  Foo<4>::f();

  Bar<3>::f();
  Bar<4>::f();
}
3 лайка

Спасибо, интересно, поигрался с примером.
Но немного не то.
Тут условие приходится задавать в определении самого шаблона, а не в специализации. А значит и условие одно, а не для каждой специализации свое.

Но все равно спасибо.

ну если вариант с std::enable_if_t не устраивает только тем, что он для с++14, такую штуку можно попробовать с++11, там есть std::enable_if или же в свой какой-то файл такое скопипастить:

template<bool B, class T = void> struct enable_if {};
template<class T> struct enable_if<true, T> { typedef T type; };

template <int A, typename = void>
class Foo {
  char* arr;
};

template <int A>
class Foo<A, typename enable_if<(A > 3)>::type>
{
  char arr[A];
};

по мне, так копипаста всяких тайп-треитсов получше, чем игры с макросами, которые должны быть определены для определенной версии плюсов.

4 лайка

Спасибо, то что нужно!