Аргументы шаблона первого типа шаблона - PullRequest
0 голосов
/ 09 мая 2018

Я использую API, который принимает функцию с единственным аргументом в качестве обратного вызова. Обратный вызов принимает один аргумент определенного типа, и для простоты я скажу, что он возвращает bool. Главной вещью, которую я пытался собрать, была функция проверки диапазона. Моей интуицией было бы написать что-то вроде этого:

template<class T, T min, T max>
constexpr bool in_range(T val) {
    return (val >= min && val <= max);
}

static_assert(in_range<float, 0.0f, 1.0f>(0.5f), "doesn't work")

Однако это не работает, поэтому я по умолчанию создал эту функцию.

template<class T>
std::function<bool(T)> in_range(T min, T max) {
    auto test = [min, max](T val) {
        return (val >= min && val <= max);
    };
    return test;
}


assert(in_range<float>(0.0f, 1.0f)(0.5f))

Есть ли способ написать функцию больше в форме первой функции, поэтому я не зависим от std::function и лямбда-выражений, генерируемых во время выполнения?

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

Есть ли способ написать функцию больше в форме первой функции, поэтому я не зависим от std :: function и лямбда-выражения, генерируемых во время выполнения?

Если вы можете передать статические глобальные переменные в качестве аргумента шаблона вместо float литералов, вы можете передать их по ссылке

Что-то следующее

#include <iostream>

template <typename T, T const & min, T const & max>
constexpr bool in_range (T val)
 { return (val >= min && val <= max); }

static constexpr float  f0 { 0.0f };
static constexpr float  f1 { 1.0f };

int main ()
 {    
   static_assert(in_range<float, f0, f1>(0.5f), "!");
 }
0 голосов
/ 09 мая 2018

Поскольку значения с плавающей запятой недопустимы в качестве нетиповых параметров шаблона, вам придется принимать их как фактические аргументы функции, а не параметры шаблона.

Если вы хотите иметь функцию, которая принимает только один аргумент, вы можете избежать стоимости std::function, возвращая лямбда-выражение напрямую. Если бы мы использовали C ++ 14, вы могли бы просто заставить его вернуть auto:

template<class T>
auto in_range(T min, T max) { // Note: could be `constexpr` in C++17
    return [min, max](T val) {
        return (val >= min && val <= max);
    };
}

Однако, так как вы используете C ++ 11, вам придется выписать вызываемый тип вручную:

template <typename T>
class InRange {
public:
    constexpr InRange(T min, T max)
        : min(std::move(min))
        , max(std::move(max))
    {}

    constexpr bool operator()(T const& val) const {
        return (val >= min && val <= max);
    }

private:
    T min;
    T max;
};

template<class T>
constexpr InRange<T> in_range(T min, T max) {
    return InRange<T>(std::move(min), std::move(max));
}
...