我一直在試驗可變參數模板和參數轉發。我認爲我發現了一些不一致的行爲。這個可變參數模板參數推導是否正確?
爲了說明,此程序:
#include <iostream>
#include <typeinfo>
#include <tuple>
#include <cxxabi.h>
template <typename... Args> struct X {};
struct A {
A() {}
A (const A &) {
std :: cout << "copy\n";
}
};
template <typename T> const char * type_name() {
return abi :: __cxa_demangle (typeid (T) .name(), 0, 0, NULL);
}
void foo() {}
template <typename... Args>
void foo (const A &, Args ... args) {
std :: cout << type_name <X <Args...>>() << "\n「; foo (args...);
}
int main() {
foo (A(), A());
}
輸出如下:
X<A, A>
copy
X<A>
即使foo的模板特具有const引用第一個參數,可變參數是按值傳遞,因爲模板類型被推斷爲非參考類型,如X<A>
輸出所示。
所以,我諮詢Thomas Becker:
template<typename T> void foo(T&&);
這裏,按照以下規定:
當調用函數foo在A型的左值,則T解析爲&和因此,通過上述參考摺疊 規則,參數類型 實際上變成A &。
當FOO上稱爲類型A的右值,則T解析爲A,和 因此參數類型成爲A & &。
而且試試這個:
template <typename... Args>
void foo (const A &, Args && ... args) {
std :: cout << type_name<X<Args...>>() << "\n";
foo (args...);
}
,輸出:
X<A, A>
X<A&>
現在我很爲難。這裏有三個foo調用。在我的腦海裏,main()
應該推導出foo<A,A,A>(A&&,A&&,A&&)
(因爲A()是一個未命名的右值,因此是一個參考),它超載 - 解析爲foo<A,A,A>(const A&,A&&,A&&)
。這又推導出foo<A,A>(A&&,A&&)
等等。
問題是:爲什麼X<A,A>
有非參考A
s但X<A&>
有一個參考A
?
這會導致問題,因爲我無法在遞歸中使用std::forward
。
你確定你的代碼對應於你的輸出嗎?我得到`X X <>`,或`main`中增加`A()`的次數,`X copy X X <>`。這是一個謎,你怎麼能`X `作爲最後一行,有或沒有&符號。無論如何,它應該是`X <>`。 – 2011-06-17 11:59:59