1. value metafunction
#include <assert>
template<int X>
struct IntIdentity {
static constexpr int my_value = X;
};
int main() {
static_assert(42 == IntIdentity<42>::my_value, " ");
return 0;
}
template <typename T, T Value>
struct ValueIdentity {
static constexpr T value = Value;
};
int main() {
static_assert(42 == ValueIdentity<int, 42>::value, " ");
static_assert(ValueIdentity<unsigned long long, 42ull>::value == 42ull, " ");
}
c++ 17 using auto in value metafunction
template <auto Value>
struct ValueIdentity {
static constexpr auto value = Value;
};
int main() {
static_assert(42 == ValueIdentity<42>::value, " ");
static_assert(ValueIdentity<42ull>::value == 42ull, " ");
}
value metafunction: sum
template <int X, int Y>
struct IntSum {
static constexpr int value = X + Y;
};
int main() {
static_assert(20 == IntSum<10, 10>::value, " 10 + 10 = 20");
}
template <typename T, T X, T Y>
struct Sum {
static constexpr T value = X + Y;
};
int main() {
static_assert(Sum<unsigned long long, 10ull, 10ll>::value == 20ull, "");
}
template <auto X, auto Y>
struct Sum {
static constexpr auto value = X + Y;
};
int main() {
static_assert(Sum<10ull,10ll>::value == 20ull, "");
}
// c++17
template <typename X, typename Y>
constexpr decltype(auto) Sum(X x, Y y) {
return x + y;
}
int main() {
static_assert(20ull == Sum<int, unsigned long long>(10, 10ull), " ");
}
Type Metafunctions
template <typename T>
struct TypeIdentity{
using type = T;
};
int main() {
return 0;
}
c++20 引入std::type_identity
value metafunctions use variavle templates ending with "_v"
template <typename T, T Value>
struct ValueIdentity {
static constexpr T value = Value;
};
template <typename T, T X>
static constexpr decltype(auto) ValueIdentity_v = ValueIdentity<T, X>::value;
int main() {
static_assert(20 == ValueIdentity<int, 20>::value, " ");
static_assert(20 == ValueIdentity_v<int, 20>, " ");
}
type metafunctions use alias templates ending with "_t"
template <typename T>
struct TypeIdentity {
using type = T;
};
template <typename T>
using TypeIdentity_t = typename TypeIdentity<T>::type;
int main() {
static_assert(std::is_same_v<int, TypeIdentity_t<int>>, " ");
}
std::integral_constant : a very useful metafunction
template <class T, T v>
struct intergral_constant {
static constexpr T value = v;
using value_type = T;
using type = intergral_constant<T, v>;
constexpr operator value_type() const noexcept {
return value;
}
constexpr value_type operator()() const noexcept {
return value;
}
};
template <class T, T v>
struct intergral_constant {
static constexpr T value = v;
using value_type = T;
using type = intergral_constant<T, v>;
constexpr operator value_type() const noexcept {
return value;
}
constexpr value_type operator()() const noexcept {
return value;
}
};
std::bool_constant
template <bool B>
using bool_constant = integral_const<bool, B>;
using true_type = bool_constant<true>;
using false_type = bool_constant<false>;
is_void (unary Type Trait)
- primary template : general case
template <typename T>
struct is_void : std::false_type {};
- specialization : special case
template <>
struct is_void<void> : std::true_type {};