可变参数模板和带有继承的默认值

时间:2018-08-15 12:43:22

标签: c++ class inheritance variadic-templates

#include <iostream>

struct A {
    int a;
    std::string b;
    A(int a_, std::string b_) : a(a_), b(b_) { std::cout << a << b << std::endl; }
};

struct B : public A {
    static const int VERSION=2;
    float c;

    template<typename ... ARGS>
    B(float c_, int v=VERSION, ARGS&&... args) : A(v, std::forward<ARGS>(args)...), c(c_) { std::cout << c << std::endl; }
};

int main() {    
    B(3.14, "abc");
}

大家好,编译器给了我模板参数推导/替换失败的错误。如何在可变参数模板中使用默认值?

variadic.cpp: In function ‘int main()’:
variadic.cpp:18:15: error: no matching function for call to ‘B::B(double, const char [4])’
  B(3.14, "abc");
               ^
variadic.cpp:14:2: note: candidate: template<class ... ARGS> B::B(float, int, ARGS&& ...)
  B(float c_, int v=VERSION, ARGS&&... args) : A(v, std::forward<ARGS>(args)...), c(c_) { std::cout << c << std::endl; }
  ^
variadic.cpp:14:2: note:   template argument deduction/substitution failed:
variadic.cpp:18:15: note:   cannot convert ‘"abc"’ (type ‘const char [4]’) to type ‘int’
  B(3.14, "abc");
               ^
variadic.cpp:9:8: note: candidate: B::B(const B&)
 struct B : public A {
        ^
variadic.cpp:9:8: note:   candidate expects 1 argument, 2 provided
variadic.cpp:9:8: note: candidate: B::B(B&&)
variadic.cpp:9:8: note:   candidate expects 1 argument, 2 provided

2 个答案:

答案 0 :(得分:1)

问题是,如果函数/方法参数具有默认值,则所有以下参数必须具有默认值。

所以

template<typename ... ARGS>
B(float c_, int v=VERSION, ARGS&&... args) 
   : A(v, std::forward<ARGS>(args)...), c(c_)
 { std::cout << c << std::endl; }

是错误的,因为args没有默认值。

或者更好:您可以编写以下签名

B(float c_, int v=VERSION, ARGS&&... args)

但仅当您将仅值(v传递给构造函数时使用c_的默认值,因为args...为空,因此v是最后一个参数

但是,如果您想要一些args...,则会忽略v的默认值,因为否则,编译器将无法知道第二个整数参数是否是{{ 1}}或第一个v

答案 1 :(得分:1)

这里的问题是,可以使用一个,两个或多个参数来调用构造函数。

如果使用一个参数调用它,则默认使用第二个参数。

如果提供两个或多个参数,则不使用提供的默认参数。您使用了第二个参数,它必须匹配第二个参数的类型。

请注意,通常,您可以通过重载函数而不提供默认参数来获得相似的结果。在这种情况下,我怀疑这会给您预期的结果,但这是我在猜测您的意图。