识别模板中的值是布尔值

Recognize that a value is bool in a template

本文关键字:布尔值 识别      更新时间:2023-10-16

这个简短的 C++17 程序:

#include <iostream>
template <typename T> void output(T x)
{
if constexpr (std::is_integral<decltype(x)>::value) {
std::cout << static_cast<int>(x) << " is integral" << std::endl;
} else {
std::cout << x << " is not integral" << std::endl;
}
}
int main()
{
char x = 65;
output(x);
bool t = true;
output(t);
return 0;
}

具有以下输出:

65 is integral
1 is integral

在名为output的模板函数中,如何检测参数x是布尔值而不是数字?

计划是输出带有std::cout << std::boolalpha <<的值,但前提是类型为bool

std::is_integral检查类型是否为以下类型之一:boolcharchar16_tchar32_twchar_tshortintlonglong long(源(。如果要检查一个类型是否与另一个类型相同,可以使用std::is_same。两者可以组合以获得所需的结果:

template <typename T> void output(T x)
{
if constexpr (std::is_integral<decltype(x)>::value && !std::is_same<decltype(x), bool>::value) {
std::cout << static_cast<int>(x) << " is integral but not a boolean" << std::endl;
} else {
std::cout << x << " is not integral" << std::endl;
}
}

或者,由于我们已经知道decltype(x)的类型,T

template <typename T> void output(T x)
{
if constexpr (std::is_integral<T>::value && !std::is_same<T, bool>::value) {
std::cout << static_cast<int>(x) << " is integral but not a boolean" << std::endl;
} else {
std::cout << x << " is not integral" << std::endl;
}
}

另一种方法是使用模板专用化。这可确保使用其他重载来处理布尔值。

template <typename T> void output(T x)
{
if constexpr (std::is_integral<T>::value) {
std::cout << static_cast<int>(x) << " is integral but not a boolean" << std::endl;
} else {
std::cout << x << " is not integral" << std::endl;
}
}
template <> void output(bool x)
{
std::cout << x << " is a boolean" << std::endl;
}
namespace fmt {
namespace adl {
template<class T>
void output( std::ostream& os, T const& t ) {
os << t;
}
void output( std::ostream& os, bool const& b ) {
auto old = os.flags();
os << std::boolalpha << b;
if (!( old & std::ios_base::boolalpha) )
os << std::noboolalpha; // restore state
}
template<class T>
void output_helper( std::ostream& os, T const& t ) {
output(os, t); // ADL
}
}
template<class T>
std::ostream& output( std::ostream& os, T const& t ) {
adl::output_helper( os, t );
return os;
}
}

现在fmt::output( std::cout, true )打印true,而fmt::output( std::cout, 7 )打印7

您可以通过在fmt::adl或名为output的类型T命名空间中创建函数来扩展fmt::output,该命名空间采用std::ostream&T const&