Почему я не могу использовать labmda в качестве нетипичного параметра шаблона? - PullRequest
1 голос
/ 01 февраля 2020

Я хочу использовать лямбду в качестве параметра шаблона, но он не скомпилируется в c ++ 17. Например, temp_bar<int, lambda1> здесь не работает. Кажется, нетипичный параметр ограничен . Может кто-нибудь объяснить, почему это не разрешено? Это облегчит жизнь.

template<typename T>
bool to_bool(T o)
{
    return bool(o);
}
template <typename T, auto F=to_bool<T>>
class temp_bar
{
public:
    temp_bar(T o)
            : _data{o}
    {
        if(F(o))
            std::cout << "OK\n";
    }
private:
    T _data;
};

int main()
{
    temp_bar<int> bar1{1};
    auto lambda1 = [](int o){return o==2;};
    temp_bar<int, lambda1> bar2{2};

    return 0;
}

Ответы [ 2 ]

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

Игнорирование того факта, что объявление lambda1 не является constexpr и, следовательно, не является константным выражением и, следовательно, никогда не может использоваться в качестве параметра шаблона нетипичного типа (NTTP) независимо от чего-либо еще, основная причина этого не допускается, что лямбды не являются чем-то особенным в C ++. Лямбда - это просто определенный пользователем тип, созданный компилятором со специализированным конструктором, членами на основе вашего списка захвата и перегрузкой operator() в соответствии с телом и сигнатурой лямбда-функции. Лямбда ничего не делает, что без них невозможно.

В C ++ лямбда - это просто сокращенная запись; ничего более.

Таким образом, если определяемые пользователем типы не могут использоваться в качестве NTTP, а лямбды являются определяемыми пользователем типами, то нельзя использовать лямбда-выражения в качестве NTTP. Вот почему они запрещены.

И обратите внимание, что, хотя C ++ 20 допускает использование некоторых пользовательских типов в качестве NTTP, стандарт в настоящее время предлагает без гарантий относительно может ли какая-то конкретная лямбда использоваться в качестве NTTP. Определенный пользователем тип, который используется в качестве NTTP, должен обеспечивать строгое структурное равенство, и ничто в стандарте не требует, чтобы любые лямбды, даже без захвата, обеспечивали строгое структурное равенство. Реализация может сделать это, но такой код непереносим.

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

Это не будет возможно без C ++ 20. Если вы хотите достичь аналогичного результата в C ++ 17, вы можете сделать следующее:

template<typename T>
bool to_bool(T o)
{
    return bool(o);
}
template <typename T >
class temp_bar
{
public:
    template <typename F >
    temp_bar(T o, F&& fn)
    : _data{o}
    {

        if(fn(o))
            std::cout << "OK\n";
    }

    temp_bar(T o) : _data(o) {
        if (to_bool(o))
            std::cout << "OK\n";
    }




private:
    T _data;


};

int main()
{
    temp_bar<int> bar1{1};
    auto lambda1 = [](int o){return o==2;};
    temp_bar<int> bar2{2,lambda1};

    return 0;
}

Это эффективно имеет два конструктора, один без лямбды и один с лямбда-выражением.

...