Как мне использовать std :: is_pod в аргументе шаблона? - PullRequest
0 голосов
/ 28 сентября 2018

Я пытаюсь получить один набор поведения, когда что-то является модулем, и что-то еще, когда это не с помощью шаблонного метапрограммирования.Я написал код ниже, но я получаю ошибку компиляции.Я хочу получить:

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 голосов
/ 28 сентября 2018
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>{} равно false, генерируется ошибка 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>{} );
}

, где мы используем обычное разрешение перегрузки для отправки междудва тела.Лично я считаю это самым вменяемым.

0 голосов
/ 28 сентября 2018

С помощью 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;
    }
}
0 голосов
/ 28 сентября 2018

Вам нужно использовать std::enable_if, чтобы использовать значение из std::is_pod в контексте SFINAE.Это выглядело бы как

// 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.

...