2015-09-25 66 views
2

我做一個簡單的,非所屬陣列視圖類:SFINAE-ING任何容器成C數組視圖

template <typename T> 
class array_view { 
    T* data_; 
    size_t len_; 
    // ... 
}; 

我想從有data()size()成員的任何容器構造它功能,但SFINAE-D正確,使得array_view是一些容器C只有constructible是否會再是有效和安全的行爲,以實際穿過data_

我去:

template <typename C, 
      typename D = decltype(std::declval<C>().data()), 
      typename = std::enable_if_t< 
       std::is_convertible<D, T*>::value && 
       std::is_same<std::remove_cv_t<T>, 
          std::remove_cv_t<std::remove_pointer_t<D>>>::value> 
      > 
array_view(C&& container) 
: data_(container.data()), len_(container.size()) 
{ } 

這似乎完全不令人滿意的,我甚至不能確定它是正確的。我是否正確地包含所有正確的容器並排除所有錯誤的容器?有沒有更簡單的方法來編寫這個要求?

+0

@dyp呀回想起來,是沒有意義的,還是讓我把它拿出來。 – Barry

+0

那麼與建議的'array_view'有什麼關係?例如。 [N4512](HTTP://開放-STD。org/JTC1/SC22/WG21/docs/papers/2015/n4512.html)(不知道這是否是當前版本)。你想讓我們批評那篇論文,或者比較你的論文嗎? – dyp

+0

@dyp從來沒有聽說過那篇論文,所以......我不知道。無論你想回答:) – Barry

回答

3

如果我們看一看在N4512提出的std::experimental::array_view,我們發現在表下面Viewable要求104:

 
Expression Return type     Operational semantics 

v.size() Convertible to ptrdiff_t 

v.data() Type T* such that T* is  static_cast(v.data()) points to a 
      implicitly convertible to U*, contiguous sequence of at least 
      and is_same_v<remove_cv_t<T>, v.size() objects of (possibly 
      remove_cv_t<U>> is true.  cv-qualified) type remove_cv_t<U>. 

也就是說,筆者使用的基本上是.data()相同的檢查,但另增加一個用於.size()

爲了通過使用操作與T使用指針運算上U,其種類必須根據[expr.add] P6是類似相似度是爲資格轉換而定義的,這就是爲什麼檢查隱式可轉換性然後檢查相似性(通過is_same)對於指針算術是足夠的。

當然,還有對操作語義沒有保證。


在標準庫,唯一的連續容器std::arraystd::vector。還有std::basic_string具有.data()成員,但是,std::initializer_list不會盡管它是連續的。

所有的.data()成員函數爲每個類的規定,但他們都返回一個實際的指針(沒有迭代,無代理)。

這意味着檢查的.data()存在是目前足以標準庫的容器;您希望添加可兌換支票以使array_view不那麼貪婪(例如,array_view<int>拒絕某些char* data())。


該實現當然可以從接口移開;你可以使用概念,概念模擬或簡單的enable_if與適當的類型函數。例如。

template<typename T, typename As, 
     typename size_rt = decltype(std::declval<T>().size()) 
     typename data_rt = decltype(std::declval<T>().data())> 
constexpr bool is_viewable = 
    std::is_convertible_v<size_rt, std::ptrdiff_t> 
    && std::is_convertible_v<data_rt, T*> 
    && std::is_same_v<std::remove_cv_t<T>, std::remove_cv_t<data_rt>>; 

template <typename C, 
      typename = std::enable_if_t<is_viewable<C, T>> 
     > 
array_view(C&& container) 
    : data_(container.data()), len_(container.size()) 
{ } 

是的,這不符合一類函數通常的技術,但它是短,你的想法。

+0

不確定你的預期,巴里。我會猜你已經找到了所有這些信息。但我不認爲這個檢查的非概念版本要短得多。 – dyp

+0

是的,我想我是希望有一些我錯過了。我確實喜歡把這個檢查放在constexpr函數中。 – Barry