если использование constexpr для элемента переменной длины Get <> - PullRequest
0 голосов
/ 25 сентября 2018

Я пытаюсь получить второй элемент списка, но получаю ошибку:

    ||=== Build: Debug in hellocpp17 (compiler: GNU GCC Compiler) ===|
/home/idf/Documents/c++/hellocpp17/main.cpp||In function ‘int main()’:|
/home/idf/Documents/c++/hellocpp17/main.cpp|67|error: no matching function for call to ‘Get<2>::Get(std::__cxx11::list<unsigned int>&)’|
/home/idf/Documents/c++/hellocpp17/main.cpp|40|note: candidate: constexpr Get<2>::Get()|
/home/idf/Documents/c++/hellocpp17/main.cpp|40|note:   candidate expects 0 arguments, 1 provided|
/home/idf/Documents/c++/hellocpp17/main.cpp|40|note: candidate: constexpr Get<2>::Get(const Get<2>&)|
/home/idf/Documents/c++/hellocpp17/main.cpp|40|note:   no known conversion for argument 1 from ‘std::__cxx11::list<unsigned int>’ to ‘const Get<2>&’|
/home/idf/Documents/c++/hellocpp17/main.cpp|40|note: candidate: constexpr Get<2>::Get(Get<2>&&)|
/home/idf/Documents/c++/hellocpp17/main.cpp|40|note:   no known conversion for argument 1 from ‘std::__cxx11::list<unsigned int>’ to ‘Get<2>&&’|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

Программа:

#include <iostream>
#include <algorithm>
#include <list>

using namespace std;

template<unsigned n>
struct Get
{
    template<class X, class...Xs>
    constexpr auto operator()(X x, Xs...xs)
    {
        if constexpr(n > sizeof...(xs) )
        {
            return;
        }
        else if constexpr(n > 0)
        {
            return Get<n-1> {}(xs...);
        }
        else
        {
            return x;
        }
    }
};



int main()
{
    list<unsigned> l = { 7, 5, 16, 8 };
    unsigned l2 = Get<2>(l);

    cout << l2 << endl;

    return 0;
}

РЕДАКТИРОВАТЬ 1

Если я создаю экземпляр Get<2>, об этой ошибке сообщает компилятор

unsigned l2 = Get<2>()(l);

/home/idf/Documents/c++/hellocpp17/main.cpp|67|error: void value not ignored as it ought to be|

1 Ответ

0 голосов
/ 25 сентября 2018

Вы можете попробовать с

unsigned l2 = Get<2>{}(7, 5, 16, 8);

Первая проблема в вашем коде заключается в том, что

Get<2>(l);

не является вызовом operator() из Get<2>;это конструкция Get<2> объекта с параметром std::list.

К сожалению, нет конструктора Get<2>, который получает std::list.

Вторая проблема в вашемкод состоит в том, что если вы вызываете operator() из Get<2>, как вы думаете

Get<2>{}(l)

, где l является std::list, вы передаете один аргумент;не вариативный список аргументов.И вы можете использовать список l только во время выполнения, а не во время компиляции, как вам нужно.

К сожалению, способ Get<2>{}(7, 5, 16, 8) (operator(), который получает список переменных аргументов) несовместим спеременная, которая содержит список.

Я имею в виду ... вы не можете сделать что-то следующим образом

auto l = something{7, 5, 16, 8};

Get<2>{}(l);

Но, если вы измените operator(), чтобы получить std::integer_sequence какследует

template <template <typename X, X...> class C,
          typename T, T I0, T ... Is>
constexpr auto operator() (C<T, I0, Is...> const &)
 {
   if constexpr (n > sizeof...(Is) )
      return;
   else if constexpr (n > 0)
      return Get<n-1>{}(C<T, Is...>{});
   else
      return I0;
 }

вы можете пройти через l переменную следующим образом

auto l { std::integer_sequence<int, 7, 5, 16, 8>{} };

unsigned l2 = Get<2>{}(l);
...