Ich bin interessiert zu verstehen, welche Arten von Vorlagen als das erste Argument von std::experimental::is_detected
und ähnliche Erkennungsdienstprogramme verwendet werden können.Welche Arten von Vorlagen können mit is_detected verwendet werden?
Unten ist eine Implementierung von is_detected
eingefügt und ein Versuch, es zu verwenden, um zu erkennen, ob ein Typ T
eine Mitgliedsfunktion hat, die .foo()
benannt wird. Das allgemeine Muster verwendet es ist, zuerst einen Typ Merkmal zu definieren, die den Typ einer Elementfunktion zurückgibt T::foo
, wenn es vorhanden ist:
template<class T>
struct member_foo_result
{
using type = decltype(std::declval<T>().foo());
};
Dann legt er eine Kurz alias:
template<class T>
using member_foo_result_t = typename member_foo_result<T>::type;
Das Problem ist, dass der Stenogramm-Alias mit inkompatibel zu sein scheint.
Hier ist das vollständige Programm, mit Compiler Ausgabe:
#include <utility>
#include <type_traits>
#include <iostream>
// implementation of is_detected
template<class...>
using void_t = void;
struct nonesuch
{
nonesuch() = delete;
~nonesuch() = delete;
nonesuch(const nonesuch&) = delete;
void operator=(const nonesuch&) = delete;
};
template<class Default, class AlwaysVoid,
template<class...> class Op, class... Args>
struct detector
{
using value_t = std::false_type;
using type = Default;
};
template<class Default, template<class...> class Op, class... Args>
struct detector<Default, void_t<Op<Args...>>, Op, Args...>
{
using value_t = std::true_type;
using type = Op<Args...>;
};
template<template<class...> class Op, class... Args>
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
// returns the result type of T::foo()
template<class T>
struct member_foo_result
{
using type = decltype(std::declval<T>().foo());
};
// shorthand alias for member_foo_result<T>::type
template<class T>
using member_foo_result_t = typename member_foo_result<T>::type;
// detects whether or not the member function T::foo() exists
template<class T>
struct has_foo_member : is_detected<member_foo_result_t, T> {};
struct doesnt_have_foo_member {};
int main()
{
std::cout << "result: " << has_foo_member<doesnt_have_foo_member>::value << std::endl;
}
ich dieses Programm erwarten drucken "Ergebnis: 0" zur Laufzeit. Allerdings ist kompilieren es nicht richtig:
$ clang -std=c++11 test_is_detected.cpp
test_is_detected.cpp:41:43: error: no member named 'foo' in 'doesnt_have_foo_member'
using type = decltype(std::declval<T>().foo());
~~~~~~~~~~~~~~~~~^
test_is_detected.cpp:45:1: note: in instantiation of template class 'member_foo_result<doesnt_have_foo_member>' requested here
using member_foo_result_t = typename member_foo_result<T>::type;
^
test_is_detected.cpp:27:33: note: in instantiation of template type alias 'member_foo_result_t' requested here
struct detector<Default, void_t<Op<Args...>>, Op, Args...>
^
test_is_detected.cpp:33:1: note: during template argument deduction for class template partial specialization 'detector<type-parameter-0-0, void, Op, type-parameter-0-2...>' [with Default = nonesuch, Op =
member_foo_result_t, Args = <doesnt_have_foo_member>]
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
^
test_is_detected.cpp:50:25: note: in instantiation of template type alias 'is_detected' requested here
struct has_foo_member : is_detected<member_foo_result_t, T> {};
^
test_is_detected.cpp:58:30: note: in instantiation of template class 'has_foo_member<doesnt_have_foo_member>' requested here
std::cout << "result: " << has_foo_member<doesnt_have_foo_member>::value << std::endl;
^
1 error generated.
Bin ich is_detected
mißbrauchen?