Использование enable_if для аргумента шаблона по умолчанию для лямбда-выражения constexpr

Я пытаюсь написать общую функцию, которая всегда будет возвращать -1. Я хочу, чтобы список аргументов шаблона по умолчанию был равен int. Я пытаюсь использовать std::enable_if или std::enable_if_t, чтобы проверить, является ли тип T допустимым арифметическим типом, используя std::is_arithmetic или std::is_arithmetic_v. У меня проблемы с синтаксисом, чтобы правильно скомпилировать это. Вот как выглядит моя лямбда:

template<typename T = int,
std::enable_if_t<std::is_arithmetic_v<T>> >
static constexpr T negative_one = [](){ 
    return static_cast<T>(-1); 
};

Это очень тривиальная функция и концепция, но компилятор хочет пожаловаться, что аргумент по умолчанию не находится в конце списка аргументов... Как бы выглядело его правильное определение?

Вот как я бы его использовал:

{
    int i = negative_one();
    float f = negative_one<float>();
}

person Francis Cugler    schedule 03.02.2021    source источник


Ответы (1)


Используйте необязательный аргумент шаблона, не являющийся типом, для sfinae. Ваш тип должен быть лямбда-типом (не T), если вы хотите вызвать его/передать как предикат. Вы можете добиться этого с помощью автоматического вывода типа.

template<typename T = int, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
static constexpr auto negative_one = [](){ 
    return static_cast<T>(-1); 
};

Другим вариантом может быть использование функции вместо лямбды:


template<typename T = int, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
static constexpr T negative_one() { 
    return static_cast<T>(-1); 
};
person bolov    schedule 03.02.2021
comment
Я ценю оба случая, но я могу передать это как предикат, где можно использовать лямбда! Но я не знал о вызове лямбды на этом сайте объявления-определения... Мне также не хватало части class = . Большое спасибо! - person Francis Cugler; 03.02.2021
comment
Однако есть одна проблема, когда я использую лямбду, она жалуется, что int i = negative_one; отсутствует требуемый аргумент шаблона. Вся цель этого заключалась в том, чтобы int было значением по умолчанию, где мне не нужно указывать, что это int, но для других типов, таких как float, double, char, bool, они должны быть выражены. - person Francis Cugler; 03.02.2021
comment
Да, это простой тривиальный случай, но из этой модели я могу построить все свои константы... Теперь я могу сделать свои negate lambda тем же способом, который будет отрицать любое значение, переданное по ссылке. - person Francis Cugler; 03.02.2021
comment
Работает как шарм! Теперь у меня есть это и моя отрицательная лямбда, и она работает! - person Francis Cugler; 03.02.2021
comment
Теперь, если бы С++ допускал шаблоны переменных, которые могут иметь тип constexpr, то мне, вероятно, это не обязательно нужно, но мой компилятор даже с С++ 17 не поддерживает их полностью, особенно вне объекта класса. . - person Francis Cugler; 03.02.2021
comment
какой компилятор? gcc и clang полностью поддерживают C++17 - person bolov; 03.02.2021
comment
Ну, я имею в виду предикат... - person Francis Cugler; 03.02.2021
comment
Визуальная студия, ха-ха - person Francis Cugler; 03.02.2021
comment
Предпочитаю std::enable_if_f<cond<T>, int> = 0 typename = std::enable_if_f<cond<T>>, последний можно угнать (negative_one<SomeType, int>). - person Jarod42; 03.02.2021
comment
Да, я могу использовать некоторые формы шаблонов переменных, но у меня нет их полной поддержки... когда я доберусь до этого и почищу свой компьютер, я действительно верю, что VS2019 поддерживает их, особенно с C++. 20. - person Francis Cugler; 03.02.2021
comment
это становится намного лучше с концепциями C++20 godbolt.org/z/ETv3YW - person bolov; 03.02.2021
comment
и да, последуйте совету Jarod42 - person bolov; 03.02.2021
comment
Я попытался изменить его на форму Джарода, но теперь компилятор сходит с ума... - person Francis Cugler; 03.02.2021
comment
Я думаю, я понял это... ему не понравилось = рядом с закрытием > для std::enable_if_t, как только я добавил пробел между ними, компилятор перестал жаловаться... - person Francis Cugler; 03.02.2021
comment
Да, это именно то, что я искал. Я думаю, что я выберу лямбда-версию, так как это функция nameless-anonymous... и все это делается во время компиляции. Теперь осталось только поместить его в соответствующий namespace! - person Francis Cugler; 03.02.2021