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

时间:2018-09-28 15:39:48

标签: c++ templates template-meta-programming typetraits

当某物是豆荚时,我试图得到一套行为,而当它不是通过模板元编程时,我试图得到另一种行为。我已经编写了以下代码,但是出现编译错误。我想得到:

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;
}

有什么建议吗?

3 个答案:

答案 0 :(得分:4)

您需要在SFINAE上下文中使用std::enable_if来使用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中删除。

答案 1 :(得分:1)

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>{} );
}

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

答案 2 :(得分:0)

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

template <class Z>
void x()
{
    if consexpr (std::is_pod<Z>::value) {
        std::cout << "yep" << std::endl;
    } else {
        std::cout << "nope" << std::endl;
    }
}