通常,类型的运行时查询在使用泛型 lambda(也具有泛型参数)的函数式编程中是有意义的。否则,简单的答案可能是:只需声明使用“必需”类型或使用类型特征等……回到泛型 lambda 的主题。
/// <summary>
/// c++ 17 generic lambdas have issues
/// with required types of auto arguments
/// in c++20 this will be fixed with new
/// lambda arguments template declaration syntax
/// until then ...
/// </summary>
namespace required_types
{
template<typename RQ>
inline auto is_required_type = [](const auto & v_ = 0) constexpr -> bool
{
using T = std::decay_t< decltype(v_) >;
return std::is_same<T, RQ>();
};
inline auto is_uint64 = [] ( const auto & v_ = 0 ) constexpr -> bool
{
return is_required_type<std::uint64_t>(v_);
};
} // required_types
namespace {
using namespace required_types;
inline auto tv = [](const char prompt[] = "", const auto & value) {
std::cout << prompt << "\ntype:\t" << typeid(decltype(value)).name() << "\nvalue:\t" << value;
};
inline auto make_double_value = [](auto value)
{
if constexpr (is_uint64(value)) {
tv("\n\nDoubling required type (std::uint_64):", value);
return value + value;
}
tv("\n\nWill try to double 'illegal' type", value);
return value + value;
};
}
一些用法
// call with 'legal' aka required type
std::uint64_t u42 = 42u;
auto double_value_2 = make_double_value(u42);
tv("\nResult:", double_value_2);
// call with some 'illegal' types also works
auto double_value = make_double_value(42u);
tv("\nResult:", double_value);
std::string one{"--ONE--"};
auto double_value_3 = make_double_value(one);
tv("\nResult:", double_value_3 );
当然,如果有人强烈反对我的介绍,仍然可以使用我的“required_types”:
template<typename T>
void some_proc ( const T && val_ ) {
using namespace required_types;
if constexpr ( is_required_type<std::uint64_t>(val_) ) {
do_something_with_uint64 (val_) ;
}
}
而不是上面我宁愿在这个答案的某个地方使用std::enable_if 。
但是(如前所述)为了解决 C++17 中的几个通用 lambdas 问题,我会(大胆地)使用我的命名空间 required_types,并进行一些扩展。