簡體   English   中英

關於模板實例化點的一些問題

[英]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.

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