簡體   English   中英

使用void_t檢測成員

[英]Member detection using void_t

對於C ++ 14中的成員檢測,我在這里使用了基於示例的代碼,但它似乎沒有用。

一個完整的例子:

#include <string>

template <typename...>
using void_t = void;

template <typename, typename = void> class HasMember_substr : public std::false_type {};
template <typename T> class HasMember_substr<T, void_t<typename T::substr>> : public std::true_type {};

template <typename, typename = void> class HasMember_fff : public std::false_type {};
template <typename T> class HasMember_fff<T, void_t<typename T::fff>> : public std::true_type {};

static_assert(HasMember_substr<std::string>::value, "");
static_assert(!HasMember_fff<std::string>::value, "");

int main() { return 0; }

在OS X上使用clang++ --std=c++14 test.cpp編譯,編譯器版本( clang++ --version ): Apple LLVM version 7.0.2 (clang-700.1.81)

第二個斷言成功,但第一個失敗。 為什么? 我也嘗試使用decltype(T::substr)而不是typename T::subset ,結果相同。

尋找T::substr與查找名為substr的成員函數不同。 gcc.godbolt.org的例子

您可以使用std::declval<T>()並使用decltype來獲取成員函數的返回類型來檢查成員函數是否存在。

如果成員函數存在,則decltype(...)將是格式良好的表達式,並且不會觸發SFINAE - 因此static_assert將正常工作。

#include <string>
#include <type_traits>
#include <utility>

template <typename...>
using void_t = void;

template <typename, typename = void> 
class HasMember_substr : public std::false_type {};

template <typename T> 
class HasMember_substr<T, void_t<
     decltype(std::declval<T>().substr(1, 1))>
> : public std::true_type {};

static_assert(HasMember_substr<std::string>::value, "");

int main() { return 0; }

請注意, decltype(std::declval<T>().substr(1, 1))檢查T是否具有可以使用參數1, 1調用的substr成員。 (例如,這不能保證是成員函數,也可以是函子數據成員。)


正如AndyG在評論中所說,另一種可能的方法是使用decltype來“驗證”成員函數指針的類型。

例:

HasMember_substr<T, void_t< decltype(&T::substr)>

請注意,如果名稱substr已重載,則此操作無效 ,並且無法保證在標准庫中使用任何類型

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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