2013-06-12 208 views
10

我想在C++ 11中重載std::is_pointer以產生std::shared_ptr<T>也是如此,因爲後者的行爲非常像T*C++ 11:將std :: is_pointer擴展到std :: shared_ptr

#include <type_traits> 

namespace std { 

template <typename T> struct is_pointer<shared_ptr<T>> : std::true_type {}; 
template <typename T> struct is_pointer<shared_ptr<T const>> : std::true_type {}; 

} 

我想知道爲什麼這個過載還沒有包含在標準實現中。有沒有我忽略的陷阱?

作爲替代方案當然可以引入一個新的特點is_shared_ptr<T>

其實,我嘗試下面的代碼在首位:

template <typename T> 
struct is_pointer<shared_ptr<typename std::remove_cv<T>::type>> 
    : std::true_type 
{}; 

不與GCC 4.7編譯由於

error: template parameters not used in partial specialization: 
error:   ‘T’ 
+3

''is_pointer'在模板編程中很有用,當我想知道某些東西是否是原始指針類型,而不僅僅是指針。如果'* p'和'++ p'是有效的表達式,你可以實現一個'is_like_ptr',它執行類似SFINAE的測試。 – aschepler

+3

@aschepler:智能指針通常不支持算術。 'is_dereferencable',只是檢查'* p',可能更合適。 –

+0

好點。我覺得我還沒有醒過來。 – aschepler

回答

10

std::is_pointer莫名其妙來自升壓和原本打算只在這裏檢測原始指針和函數指針是底部注意,您可以在Boost documentation發現:

is_pointer檢測到「真正的」指針類型而已,而不是聰明的指針。用戶不應該爲智能指針類型專門設置is_pointer,否則可能會導致Boost(和其他第三方)代碼無法正常工作。希望特徵檢測智能指針的用戶應該創建自己的指針。但是,請注意,通常無法自動檢測智能指針類型,因此,對於每個支持的智能指針類型,這種特徵必須部分專用。

它們可能只是在標準庫中具有相似性,以便爲已經使用它的用戶保持低水平的驚喜。無論如何,正如你剛纔演示的那樣,創建你自己的特徵來檢測智能指針是很容易的。

基本上,你所看到的將是尋找實現Dereferenceable概念的類型的特徵(即使這個類型也適用於std::optional而不僅僅是指針/智能指針)。

爲了完整起見,Boost的is_pointer設計僅用於檢測原始指針而不是類指針類。但其他答案應該已經給你提供了一些非常好的信息。

+3

我認爲'Dereferencable'概念更合適,因爲智能指針不能遞增,遞減和所有其他限定隨機訪問迭代器的東西。 –

+0

@ArneMertz固定,謝謝:) – Morwenn

+0

我不會說它只是用於* boost * -compatibility,但是由於所有這些語言級別類型標識符的固有設計。它們被設計爲識別實際類型的變量類別,而不是更高級別的語義概念。 –

4

雖然我同意,更普遍的類型特徵,喜歡behaves_like_pointer (原諒愚蠢的名字),is_callable(對於全部東西有())或is_indexable(對於數組式的東西)會非常有用,那肯定不是什麼東西l ike is_pointer,is_functionis_array已被設計。它們是識別實際困難語言類型的特徵,與is_integral,is_classis_rvalue_reference非常相似。

因此,對於任何種類的智能指針而言,重疊is_pointer都會克服該原始目的,並且該目的是明確無誤的。但我仍然同意像is_smart_pointer,is_callable,is_nothrow_swappableis_hashable等其他更一般的概念類型類別也會非常有用。

8

我想在C++ 11中重載std :: is_pointer以便對std :: shared_ptr也產生true,因爲後者的行爲非常像T *。

它沒有。祝你好運++pp[i]shared_ptr

我想知道爲什麼這個過載還沒有包含在標準實現中。有沒有我忽略的陷阱?

它沒有被列入,因爲它簡直就是錯誤的:is_pointer告訴你,如果一個類型是指針類型(§3.9.2)。 shared_ptr不是指針類型,所以is_pointer<shared_ptr<int>::value爲真只會是錯誤的。

其實,我想擺在首位以下代碼:

template <typename T> 
struct is_pointer<shared_ptr<typename std::remove_cv<T>::type>> 
    : std::true_type 
{}; 

這到底是remove_cv做什麼呢? GCC中的以下「作品」。

template <typename T> 
struct is_pointer<shared_ptr<T>> 
    : std::true_type 
{}; 

但是,它有未定義的行爲。一般而言,如果名稱空間std中的模板不符合定義的語義,則不允許您將模板添加到模板中。如果T指針類型其中std::shared_ptr不是std::is_pointer<T>的語義是這樣的,它僅從std::true_type派生。這本身就足夠了,但在這種特殊情況下的標準實際上去禁止它明確(§20.9.2)的長度:

的程序,增加了專業化的任何定義的類模板的行爲除非另有說明,在本小節中未定義。

<type_traits>中用戶可以添加專精的唯一模板是std::common_type

+0

+1如果提到特殊的''類別模板(common_type'除外)是非法的。不幸的是,我見過甚至有經驗的程序員都建議這樣做! Obrigado。 –

+0

C++ 17結構化綁定現在也期望用戶專注於''。 – user2023370

0

其他答案涵蓋了技術細節和一些背景。

std ::中的type_traits的想法是提供原語。您可以使用那些開箱即用的方法,並且僅使用專業版來覆蓋您的自定義類型,以便按照原始語義正確獲取報告。

你真正想要的是什麼(IMO)不是轉移is_pointer模板,而是擁有一個查詢功能,它可以隱藏你的語義。所以這就是你應該做的:你自己的is_maybesmart_pointer <>對於原始指針和其他任何你想要的都是真實的。並在你的代碼中使用它。

根據原始想法調整原件很可能會導致ODR違規,因爲您如何知道鏈接的庫尚未使用帶有shared_ptr或is_pointer的is_pointer?

相關問題