我目前正在学习可变参数模板函数和参数打包/解包。
这是我的代码,
template<typename T, typename U>
void my_insert(std::vector<int>& v, T& t) {
int i;
if (typeid(t).name() == typeid(const char*).name()) {
i = stoi(t);
}
else if (typeid(t).name() == typeid(char).name()) {
i = t - 48;
}
else if (typeid(t).name() == typeid(int).name()) {
i = t;
}
else if (typeid(t).name() == typeid(double).name()) {
i = static_cast<int>(round(t));
}
else if (typeid(t).name() == typeid(bool).name()) {
if (t) i == 1;
else i == 0;
}
else if (typeid(t).name() == typeid(std::vector<U>).name()) {
int j = 0;
while (j < t.size()) {
my_insert(v, t[j]);
++j;
}
}
else return;
v.push_back(i);
}
template<typename T, typename U, typename ...Args>
void my_insert(std::vector<int>& v, T& t, Args&... args) {
int i;
if (typeid(t).name() == typeid(const char*).name()) {
if (isdigit(t[0])) i = stoi(t);
// else do nothing
}
else if (typeid(t).name() == typeid(char).name()) {
i = t - 48;
}
else if (typeid(t).name() == typeid(int).name()) {
i = t;
}
else if (typeid(t).name() == typeid(double).name()) {
i = static_cast<int>(round(t));
}
else if (typeid(t).name() == typeid(bool).name()) {
if (t) i == 1;
else i == 0;
}
else if (typeid(t).name() == typeid(std::vector<U>).name()) {
int j = 0;
while (j < t.size()) {
my_insert(v, t[j]);
++j;
}
}
//else do nothing
v.push_back(i);
my_insert(args...);
}
int main() {
std::vector<int> v;
my_insert(v, "123", "-8", 32, 3.14159, true, true, false, '5', "12.3");
return 0;
}
错误:没有与参数列表匹配的重载函数my_insert实例
我不明白我犯了什么错误,因为对我来说,与 aprint()
函数的相同确切实现适用于{ cout << t << endl; print(args...); }
, 带签名<typename T, typename ...Args> void print(const T& t, const Args... args)
;
我知道可变参数函数可以通过递归调用同一函数的非可变参数重载版本来实现。所谓的基本案例陈述。
话虽如此,我不确定我做错了什么。
嗯...您的代码中存在一些问题。
阻塞错误是模板参数U
template<typename T, typename U>
void my_insert(std::vector<int>& v, T& t)
template<typename T, typename U, typename ...Args>
void my_insert(std::vector<int>& v, T& t, Args&... args)
编译器无法推断它并调用函数
my_insert(v, "123", "-8", 32, 3.14159, true, true, false, '5', "12.3");
未说明U
我想这个想法是"如果T
是某种U
类型的std::vector
,则添加向量的所有元素"。如果我理解正确,我建议添加函数的不同重载版本。
其他问题...
1(在几点上你写一些东西作为
if (t) i == 1;
else i == 0;
在我看来,您使用运算符==
(比较(而不是=
(赋值(。
一般建议:启用最高警告级别以拦截此类微不足道的错误。
2( 您的使用typeid
if (typeid(t).name() == typeid(char).name())
以比较类型。
建议:改用std::is_same
if ( std::is_same<T, char>::value )
3(递归的基本情况是一个my_insert()
函数,几乎与递归版本相同;唯一的区别是没有Args...
参数和递归调用。
这很容易出错,因为如果您修改两个版本中的一个,您必须记住以相同的方式修改另一个版本。
建议:写一个空洞无所事事的地面案例;
void my_insert (std::vector<int> & v)
{ }
4(你无法编译
i = stoi(t);
当t
不是char const *
时
其他作业的类似问题。
问题是当你编写[伪代码]
if ( condition )
statement_1;
else
statement_2;
编译器必须同时编译statement_1
,并在知道编译时condition
true
或false
时编译statement_2
。
为了避免编译未使用的语句,您必须使用if constexpr
.
所以你必须写一些东西
if constexpr ( std::is_same_v<T, char const *> )
i = std::stoi(t);
else if constexpr ( std::is_same_v<T, char> )
i = t - 48;
else if constexpr ( std::is_same_v<T, int> )
i = t;
else if constexpr ( std::is_same_v<T, double> )
i = static_cast<int>(std::round(t));
else if constexpr ( std::is_same_v<T, bool> )
i = t;
不幸的是,if constexpr
仅从 C++17 开始可用。
在 C++17 之前,您必须编写不同的重载函数。
5(递归调用my_insert()
,你必须记住v
向量
my_insert(args...); // <-- wrong! no v
my_insert(v, args...); // <-- correct
6(计算"123"
可以转换为char const *
但不是char const *
(它是char const [4]
(;所以,而不是
if constexpr ( std::is_same_v<T, char const *> )
i = std::stoi(t);
你可以试试
if constexpr ( std::is_convertible_v<T, char const *> )
i = std::stoi(t);
以下是代码的可能 C++17 实现
#include <cmath>
#include <string>
#include <vector>
#include <iostream>
void my_insert (std::vector<int> const &)
{ }
template <typename T, typename ... As>
void my_insert (std::vector<int> &, std::vector<T> const &, As const & ...);
template <typename T, typename ... As>
void my_insert (std::vector<int> & v, T const & t, As const & ... as)
{
int i{};
if constexpr ( std::is_convertible_v<T, char const *> )
i = std::stoi(t);
else if constexpr ( std::is_same_v<T, char> )
i = t - 48;
else if constexpr ( std::is_same_v<T, int> )
i = t;
else if constexpr ( std::is_same_v<T, double> )
i = static_cast<int>(std::round(t));
else if constexpr ( std::is_same_v<T, bool> )
i = t;
// else ???
v.push_back(i);
my_insert(v, as...);
}
template <typename T, typename ... As>
void my_insert (std::vector<int> & v, std::vector<T> const & t,
As const & ... as)
{
for ( auto const & val : t )
my_insert(v, val);
my_insert(v, as...);
}
int main ()
{
std::vector<int> v;
std::vector<char> u { '9', '8', '7' };
my_insert(v, "123", "-8", 32, 3.14159, true, u, false, '5', "12.3");
for ( auto const & val : v )
std::cout << val << ' ';
std::cout << std::endl;
}