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

Variadic template and default value with inheritance

本文关键字:继承 默认值 变参 参数      更新时间:2023-10-16
#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

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

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

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

请注意,通常,可以通过重载函数而不是提供默认参数来实现类似的结果。在这种情况下,我怀疑这会给你你想要的结果,但这是我猜测你的意图。

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

所以

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)

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

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