【问题标题】:How a function template can deduce the number of times an initializer_list is nested?函数模板如何推断 initializer_list 嵌套的次数?
【发布时间】:2020-03-09 11:24:31
【问题描述】:

我有一个函数模板,它接受一个任意嵌套的列表并返回一个数组:

#include <array>
#include <initializer_list>

template<size_t N, typename List>
std::array<size_t,N> some_function (const List& list)
{
    // N is the number of times the list is nested.
    std::array<size_t,N> arr;
    return arr;
}

当我将这个函数用于一些嵌套的std::initializer_list时,像这样:

int main () {
    using List = std::initializer_list<std::initializer_list<double>>;
    List list = {{1.,2.,3.},{4.,5.,6.}};

    std::array<size_t,2> arr;
    arr = some_function (list);
    return 0;
}

收到无法推断类型N的错误

无法推断出模板参数‘N’

问题

  • 如何改进函数模板以推断列表嵌套的次数?
  • 对于这种情况,有没有比std::initializer_list 更好的替代方案?

【问题讨论】:

  • 你认为arrarr = some_function (list); 之后会是什么。 std::array 中的N 是数组的大小。
  • 另外,您使用的 std::array 的值类型为 std::size_t,但您的列表包含双精度值。请澄清您的问题。
  • 据我了解,赋值arr = some_function (list) 不用于类型推断。所以只使用some_function (list)。但是编译器没有办法知道数组的大小。
  • initializer_list 的大小在编译时是未知的。见:stackoverflow.com/questions/41311023/…
  • 您是否要从{{1.,2.,3.},{4.,5.,6.}} 获取{ 2, 3 }? IE。每个维度的大小?

标签: c++ c++11 templates stdinitializerlist


【解决方案1】:

你可以写两个重载的constexprfunction templates来计算嵌套次数,在std::enable_ifSFINAE的帮助下。

// types have not member type value_type
template <typename T, typename = void>
struct has_value_type: std::false_type {};
// types have member type value_type
template <typename T>
struct has_value_type<T, std::void_t<typename T::value_type>> : std::true_type {};

// return nested times as 0 for types without member type value_type
template<typename T>
constexpr std::enable_if_t<!has_value_type<T>::value, size_t> get_nested_times() {
    return 0;
}
// return nested times as 1 plus times got on the nested type recursively
template<typename T>
constexpr std::enable_if_t<has_value_type<T>::value, size_t> get_nested_times() {
    return 1 + get_nested_times<typename T::value_type>();
}

那么你可以在编译时得到嵌套时间

template<typename List>
auto some_function (const List& list)
{
    // N is the number of times the list is nested.
    constexpr auto N = get_nested_times<List>();
    std::array<size_t, N> arr;
    return arr;
}

LIVE

【讨论】:

  • 谢谢,这是一个非常好的解决方案。不过,我觉得还是要显式调用函数some_function&lt;get_nested_times&lt;List&gt;(),List&gt; ,否则类型推导会失败。
  • @Ali 如果您可以像我展示的那样更改函数签名,那么您不必这样做。您可以在some_function 中获取N,而不是将其指定为模板参数。
  • 请注意,您的示例将适用于 C++17 以及您在现场演示中编译的 C++20。
  • @songyuanyao 是的,你是对的。忘记更新函数模板的定义了。
猜你喜欢
  • 2022-11-01
  • 2011-05-11
  • 1970-01-01
  • 2020-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-19
  • 2019-06-04
相关资源
最近更新 更多