मैंने यह जांचने के लिए एक विशेषता लिखने की कोशिश की कि क्या कक्षा में स्थिर कार्य है, लेकिन यह हमेशा मुझे झूठा देता है। क्या कोई मुझे बता सकता है कि समस्या कहां है?

#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;
}

ऐसा लगता है कि इन उदाहरणों में कोई बड़ा अंतर नहीं है।

क्या कोई मुझे समझ सकता है कि पहले कोड की समस्या कहां है?

0
konstantin 1 जुलाई 2019, 17:26

1 उत्तर

सबसे बढ़िया उत्तर

C++17 पर ध्यान दें, १७.५.७.२ कहता है, कि

जब एक टेम्पलेट-आईडी एक उपनाम टेम्पलेट की विशेषज्ञता को संदर्भित करता है, तो यह उपनाम टेम्पलेट के प्रकार-आईडी में टेम्पलेट-पैरामीटर के लिए इसके टेम्पलेट-तर्कों के प्रतिस्थापन द्वारा प्राप्त संबद्ध प्रकार के बराबर होता है। [नोट: एक उपनाम टेम्पलेट नाम कभी नहीं निकाला जाता है। - अंत नोट]

यह एक चरण की प्रक्रिया है और बाद में टेम्पलेट तर्क प्रतिस्थापन यहां कभी भी लागू नहीं होता है।

आइए अपने पहले उदाहरण के साथ खेलते हैं:

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 . के कारण काम करता है

हालाँकि, यदि टेम्प्लेट-आईडी निर्भर है, तो बाद में टेम्प्लेट तर्क प्रतिस्थापन अभी भी टेम्प्लेट-आईडी पर लागू होता है

जब भी संभव हो मैं संरचना-आधारित उपनाम-आधारित टेम्पलेट्स का उपयोग करने की अनुशंसा करता हूं। नहीं तो इसे काम में लाना उतना ही कठिन होगा जितना कि आत्मदाह करना

0
Konstantin Vladimirov 19 जुलाई 2019, 15:35