簡體   English   中英

可變模板未在 MSVC 中編譯?

[英]Variadic templates not compiling in MSVC?

嘗試編譯以下代碼片段:此代碼顯然使用了 C++11 功能,並在 The C++ Programming Language book §3.4.4 中進行了描述

template<typename T>
void g(T x)
{
    std::cout << x << " ";
}

template<typename T, typename... Tail>
void f(T head, Tail... tail) {
    g(head); // do something to head
    f(tail...); // tr y again with tail
}

void f() {}

int main()
{
    f(1, "Lol", 5);
    getchar();
}

VS17 輸出:

C2672 'f': 沒有找到匹配的重載函數 Line:21

'void f(T,Tail...)':需要 2 個參數 - 0 提供 Line:19

有任何想法嗎 ?

首先是 MCVE:

template<typename T, typename... Tail>
void f(T head, Tail... tail) {
    f(tail...); // tr y again with tail
}
f(1, 2, 3);

現在實例化:

f<int, int, int>(1, 2, 3);

編譯為:

template<T = int, Tail...={int,int}>
void f(int head, int tail0, int tail1) {
    f(tail0, tail1); // tr y again with tail
}

遞歸調用是:

    f<int,int>(tail0, tail1); // tr y again with tail

編譯為:

template<T = int, Tail...={int}>
void f(int head, int tail0) {
    f(tail0); // tr y again with tail
}

遞歸調用解析為:

    f<int>(tail0); // tr y again with tail

編譯為:

template<T = int, Tail...={}>
void f(int head) {
    f(); // tr y again with tail
}

在這里我們嘗試調用f()

沒有對f()有效調用可見,因此您會收到錯誤消息。

調用f()void f() {}這里沒有幫助,因為在模板中查找是在f()可見之前完成的。

如果您想以簡單的方式解決此問題,您可以在f模板上方添加inline void f(){}

更復雜的方法?

template<class...Ts>
void f(Ts...ts) {
  using discard=int[];
  (void)discard{ 0, ( void(
    g(ts)
  ),0)...};
}

這也消除了遞歸。 或者在

template<class...Ts>
void f(Ts...ts) {
  ( (void)(g(ts)), ... );
}

這也可以更快地編譯,因為它創建的符號更少(和更短)。

這里有三件事不正確。

  1. tail參數陰影模板名稱tail
  2. 沒有可行的函數來處理遞歸調用f()基本情況
  3. f()必須在另一個f(...)之前定義,因為高級函數查找不會發生在這樣的遞歸函數中。

解決方案

將參數tail的名稱更改為其他名稱

template<typename T, typename... tail>
void f(T head, tail... ftail) { //tail here was shadowing actual template name tail so changed to ftail
    g(head); // do something to head
    f(ftail...); // try again with tail
}

當您對f()進行遞歸調用時,有時沒有值傳遞給f(..)因為每次遞歸調用都會將傳遞的參數數量減少 1。

所以假設你從f(1, "Lol", 2) ,在內部遞歸調用f("Lol", 2)這反過來調用f(2)調用f() ,但是你的函數f需要至少 1 個參數。 因此錯誤

要解決此問題,只需重載基本案例場景的f ,而無需像這樣的參數

void f(){
    //last recursive call made
}

這是完整的代碼

#include<iostream>

template<typename T>
void g(T x)
{
    std::cout << x << " ";
}

void f(){ }

template<typename T, typename... tail>
void f(T head, tail... ftail) {
    g(head); // do something to head
    f(ftail...); // try again with tail
}

int main()
{
    f(1, "Lol", 5);
    getchar();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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