如何在模板参数中使用 std::is_pod?

How do I use std::is_pod in a template argument?

本文关键字:std is pod 参数      更新时间:2023-10-16

当某些东西是 pod 时,我试图获得一组行为,而当它不是通过模板元编程时,我试图获得另一组行为。我已经编写了下面的代码,但是出现编译错误。我想得到:

yep
nope

但我收到以下编译器错误:

error C2993: 'std::is_pod<_Ty>': illegal type for non-type template parameter '__formal'

使用此代码

#include <iostream>
#include <type_traits>
struct A
{
int b;
};
struct B
{
private:
int b;
public:
int c;
};
template <class Z, std::is_pod<Z>>
void x()
{
std::cout << "yep" << std::endl;
}
template <class Z>
void x()
{
std::cout << "nope" << std::endl;
}
int main()
{
x<A>();
x<B>();
return 0;
}

有什么建议吗?

您需要使用std::enable_if才能在 SFINAE 上下文中使用std::is_pod中的值。 那看起来像

// only enable this template if Z is a pod type
template <class Z, std::enable_if_t<std::is_pod_v<Z>, bool> = true>
void x()
{
std::cout << "yep" << std::endl;
}
// only enable this template if Z is not a pod type
template <class Z, std::enable_if_t<!std::is_pod_v<Z>, bool> = true>
void x()
{
std::cout << "nope" << std::endl;
}

请注意,std::is_pod已在 C++17 中弃用,并已从 C++20 中删除。

使用 c++17,您可以使用if constexpr(即使简单的if在您的情况下就足够了,因为两个分支都有效(

template <class Z>
void x()
{
if constexpr (std::is_pod_v<Z>) {
std::cout << "yep" << std::endl;
} else {
std::cout << "nope" << std::endl;
}
}
template <class Z,
std::enable_if_t<std::is_pod<Z>{}, bool> =true
>
void x()
{
std::cout << "yep" << std::endl;
}

这将有条件地创建一个类型为bool的非类型模板参数,并将其赋true

如果is_pod<Z>{}为假,则会生成 SFINAE 故障。

您必须在其他x中实现反向条件。

另一种方法是标记调度:

namespace impl {
template <class Z>
void x(std::true_type /* is pod */ )
{
std::cout << "yep" << std::endl;
}
template <class Z>
void x(std::false_type /* is pod */ )
{
std::cout << "nope" << std::endl;
}
}
template<class Z>
void x() {
impl::x<Z>( std::is_pod<Z>{} );
}

我们使用通常的重载分辨率在两个机构之间调度。 我个人认为这是最理智的。

如果您可以使用 C++20,这里有一个使用requires的解决方案。

template <class Z>
requires std::is_standard_layout_v<Z> && std::is_trivial_v<Z>
void x()
{
std::cout << "yep" << std::endl;
}