#include <iostream>
using namespace std;
struct A final {};
struct B {};
int main()
{
cout << is_final<A>::value << endl; // Output true
cout << is_final<B>::value << endl; // Output false
return 0;
}
如何實現類is_final?
#include <iostream>
using namespace std;
struct A final {};
struct B {};
int main()
{
cout << is_final<A>::value << endl; // Output true
cout << is_final<B>::value << endl; // Output false
return 0;
}
如何實現類is_final?
類型性狀使用SFINAE成語,這使一個函數模板聲明中一個潛在的形成不良的表達通常被實現。將有問題的類型名稱替換爲聲明會導致錯誤,但錯誤在該上下文中被抑制,因此該聲明或者被使用或者不被使用。但是後備超載會補充可能缺失的聲明。另一部分代碼訪問該函數以檢測敏感過載或僅備份是否被實例化。
這不會對final
工作,因爲它只能在類的模板實例化過程中導致失敗。沒有辦法重載類,也沒有辦法暫時定義一個會失敗但不會停止編譯的類,以防從final派生類。
標準報價,C++ 11§14.8.2/ 8:
只有無效類型和表達在功能類型和它的模板參數類型的直接上下文可導致扣故障。 [注:替代類型和表達式的評估可能會導致副作用,例如類模板特化和/或函數模板特化的實例化,隱式定義函數的生成等。這些副作用不在「立即上下文「,並可能導致程序不合格。 - 注完]
不知道這是否是你想要的,但你可以做這樣的事情:
#include <iostream>
struct Foo {};
struct Bar {};
template<typename T>
struct is_final {
static const bool value = false;
};
template<>
struct is_final<Bar> {
static const bool value = true;
};
int main(void) {
std::cout << is_final<Foo>::value << std::endl;
std::cout << is_final<Bar>::value << std::endl;
}
我認爲你誤解了這個問題。 –
嗯,我明白你不能沒有指定自己,如果這個類是最終的或不是。 – gvd
@gvd'final'是一個(new,context-conditional)關鍵字,可以應用於類聲明。他想檢測它是否被使用。 – Potatoswatter
由於GCC的__is_final
intrinisic的實施者(爲PR 51365)我敢肯定它不能做在一個庫中,它需要編譯器支持。
你可以用C++ 11的SFINAE表達式功能做一些非常聰明的事情,但要檢測一個類是否是最終需要從它派生出來的,並且在模板參數推導上下文中實例化派生類型,但是從一個類派生是在一個聲明中完成的,而不是一個表達式。另外,您應該考慮是否只想知道是否使用了final
僞關鍵字,或者因爲其他原因(例如僅具有私有構造函數)而導致類不可導出。
如果這個標準需要考慮,它可能需要兩個提議 - 「is_final」和「is_derivable」,它們都實現了不同的語義。儘管在TMP中,私人構造函數並不妨礙派生,正如你通常不會構造這樣的類型一樣。 – Xeo
@Xeo'is_derivable'對於可訪問構造函數的測試來說是不恰當的,因爲您仍然可以派生並使用沒有非靜態成員的類而無需構造函數。 – Potatoswatter
......恩,我的意思是說你可以使用靜態成員。 – Potatoswatter
大膽猜測:這是不可能的。 C++類型系統不會維護給定類的子類的可遍歷鏈接,只能通過其他方式(通過繼承鏈)。你究竟想實現什麼? (仍爲+1,有趣,簡潔的問題。) –
我不確定是否有可能觸發SFINAE條件,讓你測試這個。我知道G ++實現了一個__is_final關鍵字來完成它,但這就是我發現的。它依賴於實現,但可以在有限的情況下完成。 –
我認爲這是不可能的,沒有編譯器的支持。可能值得[提出未來的標準](http://isocpp.org/forums/iso-c-standard-future-proposals)添加'std :: is_final'。 – Xeo