Reputation: 3943
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:
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?
Upvotes: 1
Views: 767
Reputation: 1058
If you can use C++20, here's a solution that uses requires
.
template <class Z>
requires std::is_standard_layout_v<Z> && std::is_trivial_v<Z>
void x()
{
std::cout << "yep" << std::endl;
}
Upvotes: 1
Reputation: 217930
With c++17, you might use if constexpr
(even if simple if
is enough in your case as both branches are valid)
template <class Z>
void x()
{
if constexpr (std::is_pod_v<Z>) {
std::cout << "yep" << std::endl;
} else {
std::cout << "nope" << std::endl;
}
}
Upvotes: 2
Reputation: 180945
You need to use std::enable_if
to use the value from std::is_pod
in a SFINAE context. That would look like
// 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.
Upvotes: 4
Reputation: 275760
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
.
If is_pod<Z>{}
is false, it generates a SFINAE failure.
You'll have to implement the inverse condition in the other 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.
Upvotes: 1