Обработка рефакторингов, шаблонов SFINAE тестов и лямбд - PullRequest
0 голосов
/ 01 февраля 2019

В следующем (академически построенном, неработающем) коде есть две «проблемы», которые я знаю, как безобразно решить.Я бы хотел симпатичную.

#include <type_traits>

template<class T> struct Integer {
    Integer(T t) { static_assert(std::is_integral_v<T>, "Must be int"); }
};

template<class T> struct Floating {
    Floating(T t) { static_assert(std::is_floating_point_v<T>, "Must be flating point"); }
};

template<class T> void brol(T t)
{
    Integer i(t); //these two cannot work together
    Floating f(t); 

    template<class U> auto stuff = [] (U& u) -> void //invalid syntax : no template on bloc scope
    { u *= 2; } 

    if(std::is_integral_v<T>)
        stuff(i);
    else
        stuff(f);
}

int main()
{
    brol(2);
    brol(2.0);
}
  1. Очевидно, я не могу построить Integer и Floating внутри, если функция brol(), из-за static_asserts.Эта проблема может быть легко решена с помощью тестов SFINAE, либо с помощью std::enable_if_v, либо с помощью некоторых ... -> decltype( ... ) хитростей.Таким же образом я могу также улучшить конец тела функции и избежать блока if / else
  2. Лямбда stuff() не может быть шаблоном (потому что компилятор утверждает, что это не может).Я * мог бы * сделать его независимым и спрятать его в подпространстве имен, но это не так здорово.

ОДНАКО, я не могу просто сделать тест SFINAE с std::enable_if, так какпрототипы будут отличаться только аргументами шаблона по умолчанию, что недопустимо (см. документацию, примечания к разделу в std::enable_if).

С другой стороны, я не знаю, как правильно решить ussie 2...

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Мне кажется, что std::conditional должен решить все ваши проблемы

template <typename T>
void brol (T t)
 {
   using U = std::conditional_t<std::is_integral_v<T>, Integer<T>, Floating<T>>;

   U u{t};

   auto stuff = [] (U & u) -> void { u *= 2; };

   stuff(u);
 }

В любом случае, проблема с лямбдой может быть решена и с помощью общей лямбды (как указано rustyx)

   auto stuff = [] (auto & u) -> void { u *= 2; };

Что касается финала, если в C ++ 17 (вы используете std::is_integral_v, значит, вы используете C ++ 17), вы также можете использовать if constexpr в аналогичных условиях

if constexpr (std::is_integral_v<T>)
    stuff(i);
else
    stuff(f);

но остается проблема, которую вы должны определить i или f.

0 голосов
/ 01 февраля 2019

Неясно, для чего предназначены ваши Integer и Floating ...

Но что касается части "template<class U> auto stuff = [](U& u)", C ++ 14 автоматически делает лямбду templateесли вы просто используете auto в качестве типа параметра:

template<class T> void brol(T t) {

    auto stuff = [](auto& u)
    { u *= 2; };

    stuff(t);
}

int main() {
    brol(2);
    brol(2.0);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...