【问题标题】:if constexpr usage for variable length element Get<>if constexpr 用于可变长度元素 Get<>
【发布时间】:2018-09-25 01:16:28
【问题描述】:

我正在尝试获取列表的第二个元素,但出现错误:

    ||=== 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&lt;2&gt;,编译器会报这个错误

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

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

【问题讨论】:

  • 你需要实例化struct Get&lt;2&gt; -- 使用unsigned l2 = Get&lt;2&gt;()(l)
  • @Fred 错误:/home/idf/Documents/c++/hellocpp17/main.cpp|67|错误: void 值不应被忽略|
  • 当你应该将多个参数传递给Get&lt;2&gt;()时,你也传递了一个std::list&lt;unsigned int&gt;

标签: c++ c++17 variadic-templates template-meta-programming constexpr


【解决方案1】:

你可以试试

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

代码中的第一个问题是

Get<2>(l);

不是对operator()Get&lt;2&gt; 的调用;它是一个带有std::list 参数的Get&lt;2&gt; 对象的构造。

不幸的是,没有一个Get&lt;2&gt; 构造函数接收std::list

您的代码中的第二个问题是,如果您按照您的想法调用Get&lt;2&gt;operator()

Get<2>{}(l)

如果lstd::list,则传递一个参数;不是参数的可变参数列表。并且您可以使用列表l 仅运行时,而不是您想要的编译时。

很遗憾,Get&lt;2&gt;{}(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);

【讨论】:

  • @Ivan - 使用另一种编写 operator() 的方法改进了答案。希望这会有所帮助。
猜你喜欢
  • 2020-09-01
  • 1970-01-01
  • 2011-05-11
  • 2019-12-14
  • 1970-01-01
  • 2022-11-17
  • 2020-05-11
  • 2012-12-25
  • 1970-01-01
相关资源
最近更新 更多