簡體   English   中英

誰能解釋我為什么這個特征不能正常工作?

[英]Could anyone explain me why this trait does not work properly?

我試圖寫一個特征來檢查一個類是否具有靜態功能,但是它總是給我錯誤。 誰能告訴我問題出在哪里?

#include <iostream>

template <template <typename...> class Trait, typename Ret, typename T>
struct is_detected : std::false_type 
{
//This helps me to check that Get_t<A> is int
static_assert(std::is_same<Trait<T>, Ret>::value, "");
};

template <template <typename...> class Trait, typename T>
struct is_detected<Trait, Trait<T>, T> : std::true_type {};

class A {
public:
  static int Get() {
    std::cout << "I'm in get\n";
    return 0;
  }
};

template <typename T>
using Get_t = decltype(T::Get());

//template <typename T>
//using supports_Get = is_detected<Get_t, int, T>;

int main() {
  std::cout << is_detected<Get_t, int, A>::value << std::endl;
  return 0;
}

以下代碼有效:

#include <iostream>
#include <type_traits>

namespace detail {
template <template <typename...> class Trait, typename V, typename T>
struct is_detected : std::false_type {};

template <template <typename...> class Trait, typename T>
struct is_detected<Trait, std::void_t<Trait<T>>, T> : std::true_type {};
}

class A {
public:
  static int Get() {
    std::cout << "I'm in get\n";
    return 0;
  }
};

template <typename T>
using Get_t = decltype(T::Get());

int main() {
  std::cout << detail::is_detected<Get_t, void, A>::value << std::endl;
  return 0;
}

這些示例之間似乎並沒有太大差異。

誰能讓我明白第一個代碼的問題在哪里?

注意C ++ 17,17.5.7.2說,

當template-id指代別名模板的特殊化時,它等效於通過將其模板參數替換為別名模板的type-id中的模板參數而獲得的關聯類型。 [注意:不會推導別名模板名稱。 —尾注]

這是一個一步的過程,后續的模板參數替換在此不再適用。

讓我們開始第一個示例:

template <template <typename> class Trait, typename Ret, typename T>
struct is_detected {};

struct A {
  static int Get() {
    return 0;
  }
};

template <typename T>
using Get_t = decltype(T::Get());

template <typename T>
struct Get_t2 {
  using Type = decltype(T::Get());
};

template <template <typename> class Trait, typename T>
struct is_detected<Trait, typename Trait<T>::Type, T> : std::true_type {};

template <template <typename> class Trait, typename T>
struct is_detected<Trait, Trait<T>, T> : std::true_type {};

現在您可以看到:

is_detected<Get_t2, int, A>::value // works, because it is normal type
is_detected<Get_t, int, A>::value // not, because it is alias

有趣的是與你的想法void_t發揮作用是因為C ++ 17 17.5.7.3

但是,如果template-id是依賴的,則隨后的模板參數替換仍然適用於template-id

我建議盡可能使用基於結構而不是基於別名的模板。 否則,使其工作就像點燃其自焚一樣困難。

暫無
暫無

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

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