[英]Some questions about the point of instantiation for template
首先,一些標准的引用段落
如果在依賴於某個周圍模板 Y 的模板參數的上下文中引用模板特化 X,則給定的實例化點取決於 Y 的實例化點。
如果 X 是 function 模板特化,則實例化點是 Y 的點。
如果 X 是 class 模板特化,則實例化點就在 Y 的實例化點之前。否則,給定的實例化點與命名空間 scope 聲明/定義 (D) 的位置相關聯,其中包含引用 X 的語句。
如果 X 是 function 模板特化,則實例化點緊跟在 D 之后。
如果 X 是 class 模板特化,則實例化點就在 D 之前。
這里有一些代碼
#include <iostream>
template<int N>
struct state {
friend auto call(state<N>);
};
template<int N>
struct add_state {
friend auto call(state<N>) {
return N;
}
};
template<typename T, int N>
T show() {
add_state<N> d;
return T{};
}
template<typename T,int N>
class data {
public:
T c = show<T,N>();
};
#1,#3,#2
int main() {
data<int, 0> t;
call(state<0>{});
}
因此,根據上述規則,當實例化 class data<int, 0>
時,實例化點在#1。
然后show<T,N>
取決於模板 class 數據的模板參數。 所以show<int,0>
的實例化點在 #2。
然后add_state<N>
取決於模板 function show 的模板參數。 所以根據規則, add_state<0>
的實例化點在#3。
在 #3 auto call(state<0>)
已定義, call(state<0>{})
應該被鏈接,但事實上,編譯器報告錯誤如下:
clang:
main.cpp:24:2: error: function 'call' with deduced return type cannot be used before it is defined
call(state<0>{});
^
main.cpp:4:14: note: 'call' declared here
friend auto call(state<N>);
^
1 error generated.
g++:
main.cpp: In function ‘int main()’:
main.cpp:24:17: error: use of ‘auto call(state<0>)’ before deduction of ‘auto’
call(state<0>{});
^
為什么? 我對實例化點的理解是否有一些錯誤? 如果不是,為什么編譯器會報告這些錯誤?
根據[temp.inst]/2.1 ,當隱式實例化 class 模板時,僅實例化朋友的聲明:
The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions , default arguments, or noexcept-specifiers of the class member functions, member classes, scoped member enumerations, static data members, member templates, and朋友;
所以在#3 auto call(state<N>)
只被聲明。 此外,普通的非限定名稱查找也找不到此聲明。
盡管如此,我認為它不會使您的代碼格式不正確。 您的代碼是如此奇怪,以至於標准委員會成員或編譯器實現者可能從未考慮過這種情況:通常在 class 中定義了內聯友元函數,這使得友元 function 通過 ADL(參數相關名稱查找)可見。 這當然也是編譯器所不具備的。
因此,在main
內部的call(state<0>{})
處, call
的聲明由 ADL 在state
的定義中找到,編譯器只是不考慮在某種程度上不相關的 ZA2F2ED4F8EBC26BBBD4add4F8EBC26BBCD4 add_state
中尋找這個 function 的潛在定義. 所以它無法推斷出auto
。
我對這件事不太自信,但希望這可能有用,我整理了另一個工作示例,而不是已經建議的示例:
#include <iostream>
// forward declaration of the
// add_state template
template<int>
struct add_state;
template<int N>
struct state {
// Note: we generate the state here
// so that the compiler will see the
// definition of the call function
add_state<N> t;
friend auto call(state<N>);
};
template<int N>
struct add_state {
friend auto call(state<N>) {
return N;
}
};
int main() {
auto val = call(state<42>{});
std::cout << val << std::endl;
return 0;
}
我不確定這是否會有所幫助。 但我希望如此,就像我一樣,我也會對一個好的解釋感興趣。
你的問題在這里:
template<int N>
struct state {
friend auto call(state<N>);//<--no way of telling return type !
};
編譯器完全沒有辦法告訴call
函數返回什么並且必須放棄。 修復也很明顯,只需給它一些可以使用的東西,例如:
friend auto call(state<N>) {return N;}
如果使用int
而不是auto
得到錯誤:
main.cpp:15: undefined reference to `call(state<0>)'
collect2.exe: error: ld returned 1 exit status
將{return N;}
添加到friend int call(state<N>)
時,效果很好。 然后將int
替換回auto
,它也可以工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.