我想使用if constexpr
而不是标记调度,但我不确定如何使用它。下面的示例代码。
template<typename T>
struct MyTag
{
static const int Supported = 0;
};
template<>
struct MyTag<std::uint64_t>
{
static const int Supported = 1;
};
template<>
struct MyTag<std::uint32_t>
{
static const int Supported = 1;
};
class MyTest
{
public:
template<typename T>
void do_something(T value)
{
// instead of doing this
bool supported = MyTag<T>::Supported;
// I want to do something like this
if constexpr (T == std::uint64_t)
supported = true;
}
};
答案 0 :(得分:5)
一种方法是定义一个constexpr谓词,用于检查其参数的类型,然后constexpr切换该谓词的结果。
我认为这种方式很好,因为它将功能逻辑与前提条件逻辑分开。
#include <iostream>
#include <cstddef>
#include <type_traits>
class MyTest
{
public:
template<typename T>
void do_something(T value)
{
// define our predicate
// lambdas are constexpr-if-possible in c++17
constexpr auto is_supported = [](auto&& x) {
if constexpr (std::is_same<std::decay_t<decltype(x)>, std::uint64_t>())
return true;
else
return false;
};
// use the result of the predicate
if constexpr (is_supported(value))
{
std::cout << "supported\n";
}
else
{
std::cout << "not supported\n";
}
}
};
int main()
{
auto t = MyTest();
t.do_something(int(0));
t.do_something(std::uint64_t(0));
t.do_something(double(0));
t.do_something(static_cast<unsigned long>(0)); // be careful with std::uint_xx aliases
}
示例结果:
not supported
supported
not supported
supported
另一种表达方式可能是:
class MyTest
{
public:
template<class T>
static constexpr bool something_possible(T&&)
{
return std::is_same<std::decay_t<T>, std::uint64_t>();
}
template<typename T>
void do_something(T value)
{
// switch behaviour on result of constexpr predicate
if constexpr (something_possible(value))
{
std::cout << "supported\n";
}
else
{
std::cout << "not supported\n";
}
}
};
答案 1 :(得分:0)
通常,类型的运行时询问在使用泛型lambda的函数式编程中是有意义的(通用参数也是如此)。否则简单的答案可能是:只需声明使用&#39; required&#39;类型或使用类型特征等...回到通用lambda的主题。
// 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 );
一些用法
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_) ;
}
}
当然如果一个人对我的介绍非常不同意,我仍然可以使用我的&#34; required_types&#34;:
{{1}}
而不是上面我宁愿使用std :: enable_if,某处along this answer。
但是(如上所述)在C ++ 17中解决一些通用的lambdas问题我会(大胆地)使用我的命名空间required_types,带有一些扩展。