可变参量模板中的模板参数推导失败

问题描述 投票:0回答:1

我正在编写一个可以将字符串向量的内容倒入变量的函数。外观如下:

#include <iostream>
#include <string>
#include <sstream>
#include <vector>

template <typename T, int N = 0>
void pour2(std::vector<std::string> const& vals, T& val) {
    std::stringstream ss; 
    ss << vals[N];
    ss >> val;
}

template <typename T, typename ...Ts, int N = 0>
void pour2(std::vector<std::string> const& vals, T& val, Ts& ...args) {
    std::stringstream ss; 
    ss << vals[N];
    ss >> val;
    pour2<Ts..., N+1>(vals, args...);
}


int main() {

    std::vector<std::string> info = {"3", "1.5", "/home/tq/playground/"};

    int sz; 
    double val;
    std::string dir;

    pour2(info, sz, val, dir);

    std::cout << "size = " << sz << std::endl;
    std::cout << "value = " << val << std::endl;
    std::cout << "dir = " << dir << std::endl;

    return 0;
}

但是,g ++-9.2抱怨这一点

test.cpp: In instantiation of ‘void pour2(const std::vector<std::__cxx11::basic_string<char> >&, T&, Ts& ...) [with T = int; Ts = {double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}; int N = 0]’:
test.cpp:30:26:   required from here
test.cpp:18:19: error: no matching function for call to ‘pour2<double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, (0 + 1)>(const std::vector<std::__cxx11::basic_string<char> >&, double&, std::__cxx11::basic_string<char>&)’
   18 |  pour2<Ts..., N+1>(vals, args...);
      |  ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
test.cpp:7:6: note: candidate: ‘template<class T, int N> void pour2(const std::vector<std::__cxx11::basic_string<char> >&, T&)’
    7 | void pour2(std::vector<std::string> const& vals, T& val) {
      |      ^~~~~
test.cpp:7:6: note:   template argument deduction/substitution failed:
test.cpp:18:19: error: wrong number of template arguments (3, should be at least 1)
   18 |  pour2<Ts..., N+1>(vals, args...);
      |  ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
test.cpp:14:6: note: candidate: ‘template<class T, class ... Ts, int N> void pour2(const std::vector<std::__cxx11::basic_string<char> >&, T&, Ts& ...)’
   14 | void pour2(std::vector<std::string> const& vals, T& val, Ts& ...args) {
      |      ^~~~~
test.cpp:14:6: note:   template argument deduction/substitution failed:

和clang-9.0.1说

test.cpp:18:2: error: no matching function for call to 'pour2'
        pour2<Ts..., N+1>(vals, args...);
        ^~~~~~~~~~~~~~~~~
test.cpp:30:2: note: in instantiation of function template specialization 'pour2<int, double, std::__cxx11::basic_string<char> , 0>' requested here
        pour2(info, sz, val, dir);
        ^
test.cpp:14:6: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'Ts'
void pour2(std::vector<std::string> const& vals, T& val, Ts& ...args) {
     ^
test.cpp:7:6: note: candidate function template not viable: requires 2 arguments, but 3 were provided
void pour2(std::vector<std::string> const& vals, T& val) {
     ^
1 error generated.

我发现如果将非类型模板参数移动为第一个参数,则代码可以按预期方式编译和运行:

template <int N = 0, typename T>
void pour(std::vector<std::string> const& vals, T& val) {
    std::stringstream ss; 
    ss << vals[N];
    ss >> val;
}

template <int N = 0, typename T, typename ...Ts>
void pour(std::vector<std::string> const& vals, T& val, Ts& ...args) {
    std::stringstream ss; 
    ss << vals[N];
    ss >> val;
    pour<N+1, Ts...>(vals, args...);
}

我只是想知道,为什么在第一种情况下它不起作用?

c++ c++11 templates variadic-templates template-argument-deduction
1个回答
1
投票

如果在参数包后出现N,则需要从函数参数推导出N或使用默认参数,并且不能通过函数参数推导出N。

“在功能模板中,模板参数包可能会出现在列表中的较早位置,条件是可以从函数参数推导出所有后续参数,或使用默认参数”。 -[parameter_pack - cppreference]

© www.soinside.com 2019 - 2024. All rights reserved.