【问题标题】:std::initializer_list as constructor argument in template classstd::initializer_list 作为模板类中的构造函数参数
【发布时间】:2020-12-13 03:09:10
【问题描述】:

我正在尝试在构造函数中使用 std::initializer_list 来接受可变数量的参数。使用非模板类它可以正常工作,但使用模板类它会产生编译错误。谁能指出我正确的方向?我的 g++ 能够使用 C++17。

#include <iostream>
#include <vector>
#include <type_traits>
#include <initializer_list>

struct Nontemplate
{
    // std::initializer_list for a function taking variable number of arguments
    template <class Iterator>
    Nontemplate(std::initializer_list<Iterator> list) {
        std::cout << "size: " << list.size() << std::endl;
        for(auto it : list) {
            std::cout << *it << std::endl;
        }
    }
};

template <class T, class TIterator>
struct Template
{
    std::vector<T> vec;

    Template(std::initializer_list<TIterator> list)
    {
        if(!std::is_same<typename std::iterator_traits<TIterator>::value_type, T>::value)
            throw std::runtime_error("Iterator value type is not the expected.");

        std::cout << "size: " << list.size() << std::endl;

        vec.clear();
        vec.reserve(list.size());
        for(T val : list)
            vec.push_back(val);
    }
};

int main()
{
    double vec[] = {0,1,2,3,4,5};

    Nontemplate cls0({vec, vec+2, vec+3, vec+4}); // no problem
    //Template cls1({vec, vec+2, vec+3, vec+4});  // compiling error
    return 0;
}

提前致谢。

【问题讨论】:

  • 您遇到了哪些编译错误?
  • @1201ProgramAlarm: 错误信息是:main.cpp:42:45: error: class template argument deduction failed: 42 |模板 cls1({vec, vec+2, vec+3, vec+4}); // 编译错误
  • 你需要在 Template,?> cls1....中传递 Template Argumnets....
  • list 的元素属于TIterator,而不是T。 TIterator 可能与 T* 相同也可能不同
  • @jianz Template&lt;double, double*&gt; 应该可以修复您的编译器错误,但这里没有模板参数推导。您可以只有一个模板参数:TIterator 并以此为基础创建您的向量:std::vector&lt;typename std::iterator_traits&lt;TIterator&gt;::value_type&gt; vec; 然后您不必自己为模板提供类型。另外它变成了编译时检查。

标签: c++ templates stdinitializerlist


【解决方案1】:

Template cls1({vec, vec+2, vec+3, vec+4})没有办法推导出T。

你可能会使用

Template&lt;double, double*&gt; cls1({vec, vec+2, vec+3, vec+4});

或提供自定义扣款指南:

template <typename It>
Template(std::initializer_list<It>)
-> Template<typename std::iterator_traits<It>::value_type, It>;

或简化您的课程以删除 T

template <class TIterator>
struct Template
{
    using T = typename std::iterator_traits<TIterator>::value_type;
    std::vector<T> vec;

    Template(std::initializer_list<TIterator> list)
    {
        std::cout << "size: " << list.size() << std::endl;

        vec.clear();
        vec.reserve(list.size());
        for(T val : list)
            vec.push_back(val);
    }
};

【讨论】:

  • 这太棒了。在您发帖之前,我一直在使用“Template” 方法。我正在寻找的是您在此处提供的另外两个替代方案。非常感谢。你能纠正错别字吗?我已经接受了这个作为解决方案。 1)自定义推导方法:“-> Template::value_type, It>;” 2) 删除 T 方法:“使用 T = typename std::iterator_traits::value_type;”
  • @jianz:错别字已修复。 (如果仍有一些,请随时编辑)。
猜你喜欢
  • 2013-10-29
  • 2016-05-31
  • 2013-06-14
  • 2011-01-22
  • 2016-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多