2

Is it possible to make class type, which is:

  • trivially move-constructible, but not trivially copy-constructible, but still copy-constructible
  • trivially copy-constructible, but not trivially move-constructible, but still move-constructible
  • trivially copy-assignable, but not trivially move-assignable, but still move-assignable
  • trivially move-assignable, but not trivially copy-assignable, but still copy-assignable
  • trivially copy/move-constructible, but not trivially copy/move-assignable, but still copy/move-assignable and vice versa
  • etc (if any)

?

How they would look like?

The question make sense for developing, say, std::variant-like or std::tuple-like class.

The question is arised after looking through this article.

Tomilov Anatoliy
  • 15,657
  • 10
  • 64
  • 169
  • What do you think? You should put forth some effort before asking others to do your work for you. – xaxxon Sep 21 '16 at 04:59
  • Also, here are the definitions: http://en.cppreference.com/w/cpp/language/copy_constructor#Trivial_copy_constructor and http://en.cppreference.com/w/cpp/language/move_constructor#Trivial_move_constructor – xaxxon Sep 21 '16 at 05:01
  • @xaxxon Sometimes the question's formulation itself is a big deal. E.g. Newton's question about gravity and many others. – Tomilov Anatoliy Sep 21 '16 at 05:02
  • 1
    What are you talking about? – xaxxon Sep 21 '16 at 05:03

2 Answers2

1

To answer what I think is the heart of your question:

The question make sense for developing, say, std::variant-like or std::tuple-like class

There are 3 kinds of class-types that are of concern here viz.

  • Owner Types
  • Regular Types
  • Other types (Functions, Mutexes)

In the following assume both assign & construct suffixes are present for move/copy. I will refer to non-trivial operations as clone-:

Owner Types: These are Movable & Clone-able ( deep copy or shallow copy are the choices to be made) Stereotypical examples are std::unique_ptr, std::shared_ptr

Regular Types(int-like): These are Movable & Copy-able. Stereotypical examples are int, std::vector. A lot more details for these types can be found at What is a "Regular Type" in the context of move semantics? & in Elements Of Programming.

Other types (Functions, Mutexes etc.): These types refuse to be put into one of the clean classes above eg. Functions may refer to a pointer, a lambda with captures etc.

As far as all the other combinations of trivially copy-able/movable are concerned while you can create such classes I think they are more like curiosities rather things you will see in any useful scenario.

I have put std::vector in Regular Types rather than Owner Types even though std::vector manages memory since its interface is designed to be as close to a regular type as possible. You can often design a Regular interface for a type which is superficially non-regular. In such scenarios reasoning about code is easier if you use a regular interface.

Community
  • 1
  • 1
-3
  1. yes
  2. yes
  3. yes
  4. yes

You'll need to be more clear on 5.

Trivial means (among other things) not user-provided. So simply explicitly writing the default implementation takes something from trivial to non-trivial.

http://eel.is/c++draft/class#class!trivially copyable

http://eel.is/c++draft/class.copy#25

xaxxon
  • 19,189
  • 5
  • 50
  • 80
  • Your answer is defenitely not constructive. – Tomilov Anatoliy Sep 21 '16 at 05:03
  • 3
    It answers your question. Perhaps you meant to ask something else? – xaxxon Sep 21 '16 at 05:04
  • 2
    @Orient The last sentence of this answer perfectly answer your question: Requirements for trivial move/copy-constructor/assignment are identical, so you just have to make one user-provided to make it non-trivial and keep the other ones trivial. – Holt Sep 21 '16 at 05:55
  • 1
    @Holt to be fair, that wasn't there at first. But still, the question is (when first posted) contextless, so the answer can't have much, either. – xaxxon Sep 21 '16 at 05:58
  • @Holt Apparently, comments are related to first version of answer (i.e. "yes yes yes yes"). – Tomilov Anatoliy Sep 21 '16 at 05:58
  • @Orient my intial answers matched your initial question. – xaxxon Sep 21 '16 at 06:01
  • @Holt there is such [class type](http://en.cppreference.com/w/cpp/language/union) as `union`. Triviality rules are much more complicated, then for `struct` or `class`. – Tomilov Anatoliy Sep 21 '16 at 06:01
  • @xaxxon My comment was directed to Holt, but not to you (note "@Holt" at the beggining of the comment). I know the history of our conversation/ – Tomilov Anatoliy Sep 21 '16 at 06:03
  • @Orient this is not the appropriate place to ask a new question. You should post a new question if you have one. – xaxxon Sep 21 '16 at 06:03
  • BTW what is "default implementation"? Do you mean "user-provided" or "user-defined" term? – Tomilov Anatoliy Sep 21 '16 at 06:06
  • 1
    @Orient Same way you do it with standard `class`, makes the move constructor defaulted (`= default`) and create a custom copy constructor: `union U { U(const U&) { }; U(U&&) = default; };` is trivially move-constructible but not trivially copy-constructible. See http://rextester.com/NXI18240. – Holt Sep 21 '16 at 06:12
  • "Trivial means not user-provided." this may be true for empty class. – Tomilov Anatoliy Sep 21 '16 at 06:20
  • 1
    @Orient "default implementation" is the implementation defined by the standard for a member function that can be implicitly declared and defined, e.g. an implicitly defined/explicitly defaulted copy/move constructor has an implementation which is well defined by the standard (e.g. an implicit copy-constructor will copy-construct all members). There is no such thing as *user-defined* for (special member) functions in the C++ standard, a *user-provided* member functions is a user-declared and not explicitly defaulted (or deleted) method (e.g. `U(U&&) = default` is not *user-provided*). – Holt Sep 21 '16 at 06:23
  • @Holt How one can write a "default implementation", not touching the sources of the compiler? =) I simply want to point out, that word "default" in the answer is unnecessary. – Tomilov Anatoliy Sep 21 '16 at 06:27
  • 2
    @Orient What xannon means is that you can reproduce the behavior of `U(const U&) = default` by doing, e.g, `U(const U &u) : a1_(u.a1_), a2_(u.a2_) { }`, making the copy-constructor **user-provided** while not changing its behavior (it has the behavior defined by the standard for an implicitly defined or defaulted copy-constructor, the so-called "default implementation"). – Holt Sep 21 '16 at 06:31
  • @Holt triviality also means, that one can emulate a trivial operation by oneself using bitwise copy of correspoinding memory. For user-provided implementation it is forbidden act. – Tomilov Anatoliy Sep 21 '16 at 06:34
  • @Orient I provided the definition of a trivial copy/move constructor as a comment to your question. If you somehow mean a different definition than the actual c++ definition, you need to specify that in your question. – xaxxon Sep 21 '16 at 06:36
  • 2
    @Orient I don't get your point - As soon as you make the copy constructor *user-provided*, even if its behavior is the same as the implicitly defined copy-constructor (as in my example), the class is not trivially copy-constructible. – Holt Sep 21 '16 at 06:37
  • @Holt do you mean, that if type trait (from family `std::is_trivially_*`) said, that some operation is not trivial, you still may legally make a bitwise copy in some cases? – Tomilov Anatoliy Sep 21 '16 at 06:39
  • @Orient Yes, exactly. – Holt Sep 21 '16 at 06:40
  • @Holt OK, I make separate question for this point. I sure, language-lawyers severally punish me for that. – Tomilov Anatoliy Sep 21 '16 at 06:41
  • To be correct: not "default implementation", but "implementation, equivalent to the default one", — isn't it? – Tomilov Anatoliy Sep 21 '16 at 06:47
  • 2
    --1 absolutely **wrong**. "Not user-provided" most certainly does *not* imply "trivially copyable". "Trivially copyable" means "`memcpy`-able". – user541686 Sep 21 '16 at 06:49
  • @Mehrdad http://eel.is/c++draft/class.copy#25 "A copy/move assignment operator for class X is trivial if it is not user-provided and..." or were you not talking to me? I'm confused now. – xaxxon Sep 21 '16 at 07:28
  • 1
    http://eel.is/c++draft/class#6 A trivially copyable class is one "where each copy constructor, move constructor, copy assignment operator, and move assignment operator ([class.copy], [over.ass]) is either deleted or trivial," – xaxxon Sep 21 '16 at 07:32
  • Oh, guys, sorry. I think I must delete this Q&A completely, who is against? – Tomilov Anatoliy Sep 21 '16 at 07:57
  • 2
    @xaxxon What Mehrdad says is that "not user-provided" is only one of the conditions, e.g. a class with a non trivially copy-constructible member and an implicitly defined copy-constructor has a not user-provided copy-constructor but is not trivially copy-constructible. – Holt Sep 21 '16 at 09:23