Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Using std::enable_if and std::is_trivially_copyable

283 views
Skip to first unread message

bitrex

unread,
Feb 20, 2017, 9:46:16 AM2/20/17
to
How do I use std::enable_if and std::is_trivially_copyable to enable or
disable a constructor depending on whether the underlying class's
template parameter is trivially copyable, or not?

I found this article:

http://seanmiddleditch.com/using-stdenable_if-on-constructors/

but I admit I don't completely understand what's going on here or how to
apply it to my situation.

Chris Vine

unread,
Feb 20, 2017, 5:01:39 PM2/20/17
to
It depends on what other constructors there are, but in C++14 something like
this will work:

template <class T,
class = std::enable_if_t<std::is_trivially_copyable<std::remove_reference_t<T>>::value>>
MyClass(T&& t) {std::cout << "In constructor\n";}

Note you cannot have a mirror constructor with a !std::is_trivially_copyable
enable_if template type because the 'class = ' form provides a default type
argument and what the compiler would then see when it comes to resolve the
overload set are two identical function declarations except having two
different default types, and at that point it cannot choose between them. To
avoid that can have an additional dummy 'class = void' template parameter on
one only of the overloads, so SFINAE works as intended, viz:

template <class T,
class = std::enable_if_t<!std::is_trivially_copyable<std::remove_reference_t<T>>::value>,
class = void>
MyClass(T&& t) {std::cout << "In constructor\n";}

Another option for std::enable_if with constructors is:

template <class T>
MyClass(T&& t,
std::enable_if_t<std::is_trivially_copyable<std::remove_reference_t<T>>::value, int> = 0)
{std::cout << "In constructor\n";}

An alternative to std::enable_if is tag dispatch.

Chris Vine

unread,
Feb 21, 2017, 4:23:10 AM2/21/17
to
On Mon, 20 Feb 2017 22:01:26 +0000
Chris Vine <chris@cvine--nospam--.freeserve.co.uk> wrote:
> On Mon, 20 Feb 2017 09:45:52 -0500
> bitrex <bit...@de.lete.earthlink.net> wrote:
> > How do I use std::enable_if and std::is_trivially_copyable to enable
> > or disable a constructor depending on whether the underlying
> > class's template parameter is trivially copyable, or not?
> >
> > I found this article:
> >
> > http://seanmiddleditch.com/using-stdenable_if-on-constructors/
> >
> > but I admit I don't completely understand what's going on here or
> > how to apply it to my situation.
>
> It depends on what other constructors there are, but in C++14
> something like this will work:

[snip]

It occurs to me on rereading this that what you may be trying to do is
to select the constructor based not on the argument passed to the
constructor (which is what my previous examples did) but on the template
type of the class itself. That is more complicated - to use std::enable_if
for this you need a combination of SFINAE with partial specialization.
This will do that for you:

#include <iostream>
#include <type_traits>
#include <string>

template <class T, class = void>
struct MyClass {
MyClass()
{std::cout << "In non-trivially copiable constructor\n";}
};

template <class T>
struct MyClass<T, std::enable_if_t<std::is_trivially_copyable<T>::value>> {
MyClass()
{std::cout << "In trivially copiable constructor\n";}
};

int main () {
MyClass<int> m1;
MyClass<std::string> m2;
}

However, in this usage I would be inclined to ignore SFINAE and std::enable_if
completely and use a template alias instead:

template <class T, bool>
struct MyClassImpl {
MyClassImpl()
{std::cout << "In non-trivially copiable constructor\n";}
};

template <class T>
struct MyClassImpl<T, true> {
MyClassImpl()
{std::cout << "In trivially copiable constructor\n";}
};

template <class T>
using MyClass = MyClassImpl<T, std::is_trivially_copyable<T>::value>;

int main () {
MyClass<int> m1;
MyClass<std::string> m2;
}

bitrex

unread,
Feb 21, 2017, 12:38:34 PM2/21/17
to
On 02/21/2017 04:22 AM, Chris Vine wrote:
> On Mon, 20 Feb 2017 22:01:26 +0000
> Chris Vine <chris@cvine--nospam--.freeserve.co.uk> wrote:
>> On Mon, 20 Feb 2017 09:45:52 -0500
>> bitrex <bit...@de.lete.earthlink.net> wrote:
>>> How do I use std::enable_if and std::is_trivially_copyable to enable
>>> or disable a constructor depending on whether the underlying
>>> class's template parameter is trivially copyable, or not?
>>>
>>> I found this article:
>>>
>>> http://seanmiddleditch.com/using-stdenable_if-on-constructors/
>>>
>>> but I admit I don't completely understand what's going on here or
>>> how to apply it to my situation.
>>
>> It depends on what other constructors there are, but in C++14
>> something like this will work:
>
> [snip]
>
> It occurs to me on rereading this that what you may be trying to do is
> to select the constructor based not on the argument passed to the
> constructor (which is what my previous examples did) but on the template
> type of the class itself. That is more complicated - to use std::enable_if
> for this you need a combination of SFINAE with partial specialization.
> This will do that for you:

Thanks! Yes, that's correct.
0 new messages