Ebony Ayers
Ebony Ayers

Reputation: 360

How to specify a custom class conforms to a standard or custom type trait

I feel like I am missing something. I cannot see anything about how I am supposed to specify my class has a trait. E.G.

#include <type_traits>
class foo
{
    type_trait trivially_copyable = true; //?
    type_trait integral = false; //?

    public:
        foo(const int& val);
        int get_x() const;
    private:
        int m_x;
};

This would be useful in the following cases:

  1. a wrapper around an int32_t to act as a Unicode character, using an int for copying optimization but not having the integral trait so standard functions don't do math on it.
  2. an object with a size_t index to a known array where a component is stored and the array object must also be copied when copying the original object. Therefore the class would not be trivially copyable despite being made of all trivially copyable primitives.
  3. objects with a unique ID that must be updated even when copying, making it non trivially copyable.
  4. A complex container type which stores the control block before the data making it trivially copyable, but also has the option to be non trivially copied to clean up fragmented memory.

I someone would please explain how to specify type traits in my own classes, that would be great.

As a follow up to number 2 and 4 if I implement a non-trivial copy constructor will the compiler mark the function automatically as not being trivially copyable (and vice-versa) or do I need to manually mark it every time?

Thanks in advance.

Upvotes: 1

Views: 995

Answers (2)

Eugene
Eugene

Reputation: 7188

You cannot specify standard traits - this is not the intention. The traits (std::is_trivially_copyable and std::is_integral) are evaluated by the standard library itself.

A class satisfies is_trivially_copyable if it does not have user-defined copy constructor, and none of its non-static data members has one either, recursively. None of user-defined classes satisfy is_integral.

So, in your example, class foo (if you remove the invalid statements that start with type_trait) automatically has the traits you want, i.e. it is trivially copyable and non-integral.

Even though you cannot explicitly specify the traits, you can verify that they are satisfied. For example:

#include <type_traits>
class foo
{
    public:
        foo(const int& val);
        int get_x() const;
    private:
        int m_x;
};
static_assert( is_trivially_copyable<foo>::value);

Starting from C++17, you can write the same assert shorter:

static_assert( is_trivially_copyable_v<foo>);

Upvotes: 2

Jeff Garrett
Jeff Garrett

Reputation: 7383

C++ type traits are implicit. You opt into or out of them by satisfying their requirements.

1: is_integral only identifies standard integral types. A wrapper type never satisfies it, even if intended for mathematical use.

2-4: You would either delete the copy constructor and make the class uncopyable, or define the copy constructor with the custom logic needed, which by itself makes the class not trivially copyable.

Upvotes: 0

Related Questions