Existe-t-il un moyen d'utiliser le idiome de détection (ou une autre méthode) pour tester si une fonction est valide pour des arguments de modèle donnés, s'il échoue à cause d'une erreur d'interprétation. static_assert
?
L'exemple ci-dessous illustre que la validité de foo
(échec du calcul du type de retour) est détecté comme prévu, mais celui de bar
(à défaut static_assert
) ne l'est pas.
#include <iostream>
#include <type_traits>
template <typename... T> using void_t = void;
template <class AlwaysVoid, template<class...> class Op, class... Args>
struct detector: std::false_type { };
template <template<class...> class Op, class... Args>
struct detector<void_t<Op<Args...>>, Op, Args...>: std::true_type { };
template <template<class...> class Op, class... Args>
constexpr bool is_detected = detector<void, Op, Args...>::value;
template <typename T>
std::enable_if_t<!std::is_void<T>::value> foo() {
std::cout << "foo" << std::endl;
}
template <typename T>
void bar() {
static_assert( !std::is_void<T>::value );
std::cout << "bar" << std::endl;
}
template <typename T> using foo_t = decltype(foo<T>());
template <typename T> using bar_t = decltype(bar<T>());
int main(int argc, char* argv[]) {
foo<int>();
// foo<void>(); // fails as expected
bar<int>();
// bar<void>(); // fails as expected
std::cout << std::boolalpha;
// detection works for foo
std::cout << is_detected<foo_t,int > << std::endl; // true
std::cout << is_detected<foo_t,void> << std::endl; // false
// but not for bar
std::cout << is_detected<bar_t,int > << std::endl; // true
std::cout << is_detected<bar_t,void> << std::endl; // true !!!
}
C'est la raison pour laquelle je ne peux pas détecter si une boost::lexical_cast
est valable pour les types donnés.