簡體   English   中英

主函數體未檢測到對重載可變參數模板函數 C++ 的調用

[英]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是某種類型Ustd::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;

當知道編譯時conditiontruefalse時,編譯器也必須同時編譯statement_1statement_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM