Created
November 1, 2016 08:19
-
-
Save remyroez/4581b8924c9a5a0ef5c6d0e055693ea5 to your computer and use it in GitHub Desktop.
SFINAE 特定のメンバ変数を持っているかどうかの trait
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <type_traits> | |
struct has_value_impl { | |
template <class T, class U = decltype(T::value)> | |
constexpr static std::is_same<U, int> test_variable(int); | |
template <typename...> | |
constexpr static std::false_type test_variable(...); | |
template <class T, class U = decltype(std::declval<T&>().value())> | |
constexpr static std::is_same<U, int> test_func(int); | |
template <typename...> | |
constexpr static std::false_type test_func(...); | |
}; | |
template <class T> | |
constexpr bool has_variable_value = decltype(has_value_impl::test_variable<T>(0))::value; | |
template <class T> | |
constexpr bool has_func_value = decltype(has_value_impl::test_func<T>(0))::value; | |
template <class T> | |
constexpr bool has_value = has_variable_value<T> || has_func_value<T>; | |
struct value_trait { | |
template <typename T, std::enable_if_t<has_variable_value<T>, std::nullptr_t> = nullptr> | |
static int get(const T &t) { return t.value; } | |
template <typename T, std::enable_if_t<has_func_value<T>, std::nullptr_t> = nullptr> | |
static int get(const T &t) { return t.value(); } | |
}; | |
struct foo { | |
int value; | |
}; | |
struct bar { | |
int value() const { return 456; } | |
}; | |
struct baz { | |
float value; | |
}; | |
template <typename T, std::enable_if_t<has_value<std::decay_t<T>>, std::nullptr_t> = nullptr> | |
void print_value(const T &t) { | |
std::cout | |
<< " has value: " | |
<< value_trait::get(t) | |
<< std::endl; | |
} | |
template <typename T, std::enable_if_t<!has_value<std::decay_t<T>>, std::nullptr_t> = nullptr> | |
void print_value(const T &t) { | |
(void)t; | |
std::cout | |
<< " doesn't have value" | |
<< std::endl; | |
} | |
int main() | |
{ | |
foo a{123}; | |
bar b; | |
baz c{789.0f}; | |
int d = 1000; | |
std::cout << "a"; | |
print_value(a); | |
std::cout << "b"; | |
print_value(b); | |
std::cout << "c"; | |
print_value(c); | |
std::cout << "d"; | |
print_value(d); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment