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

时间:2021-08-16 15:01:34

I'm trying to get one set of behavior when something is a pod, and something else when it's not through template meta programming. I've written the below code, but I get a compilation error. I want to get:

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

yep
nope

but I get the following compiler error:

但是我得到以下编译器错误:

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

Using this code

使用此代码

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

Any advice?

3 个解决方案

#1


4  

You need to use std::enable_if to use the value from std::is_pod in a SFINAE context. That would look like

您需要使用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;
}

Do note that std::is_pod is deprecated in C++17 and has been removed from C++20.

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

#2


1  

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

this conditionally creates a non-type template parameter of type bool, and assigns it true.

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

If is_pod<Z>{} is false, it generates a SFINAE failure.

如果is_pod {}为false,则会生成SFINAE失败。

You'll have to implement the inverse condition in the other x.

你必须在另一个x中实现逆条件。

An alternative is tag dispatching:

另一种方法是标签调度:

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

where we use usual overload resolution to dispatch between the two bodies. I, personally, find this the most sane.

我们使用通常的重载决策来在两个主体之间进行分派。我个人认为这是最理智的。

#3


0  

With c++17, you might use if constexpr (even if simple if is enough in your case as both branchs are valid)

使用c ++ 17,你可以使用constexpr(即使在你的情况下很简单,因为两个分支都是有效的)

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

#1


4  

You need to use std::enable_if to use the value from std::is_pod in a SFINAE context. That would look like

您需要使用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;
}

Do note that std::is_pod is deprecated in C++17 and has been removed from C++20.

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

#2


1  

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

this conditionally creates a non-type template parameter of type bool, and assigns it true.

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

If is_pod<Z>{} is false, it generates a SFINAE failure.

如果is_pod {}为false,则会生成SFINAE失败。

You'll have to implement the inverse condition in the other x.

你必须在另一个x中实现逆条件。

An alternative is tag dispatching:

另一种方法是标签调度:

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

where we use usual overload resolution to dispatch between the two bodies. I, personally, find this the most sane.

我们使用通常的重载决策来在两个主体之间进行分派。我个人认为这是最理智的。

#3


0  

With c++17, you might use if constexpr (even if simple if is enough in your case as both branchs are valid)

使用c ++ 17,你可以使用constexpr(即使在你的情况下很简单,因为两个分支都是有效的)

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