![](/img/trans.png)
[英]Overloading variadic-templated member function and variadic-templated functions
[英]Main function body doesn't detect call to overloaded variadic-templated function C++
我目前正在學習可變參數模板函數和參數打包/解包。
這是我的代碼
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 的實例與參數列表匹配
我不明白我犯了什么錯誤,因為對我來說 a print()
函數的完全相同的實現適用於{ cout << t << endl; print(args...); }
{ cout << t << endl; print(args...); }
{ cout << t << endl; print(args...); }
, w/ signature <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;
當知道編譯時condition
為true
或false
時,編譯器也必須同時編譯statement_1
和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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.