How to disable implicit constructor conversion, allowing copy-initialization

Assuming we have something like:

class U { ... } 

and

 class T { T(const U&) { ... } } 

Now I can declare a variable as follows: U foo; , then T blah(foo); or T blah = foo

Personally, I prefer later.

Now, do I need to change the T-copy constructor to:

 class T { explicit T(const U&) { ... } } 

I can declare a variable as: T blah(foo); T blah = foo; will give me a compilation error about the impossibility of converting U to T.

http://en.cppreference.com/w/cpp/language/explicit explains that behavior with: "Defines constructors and (since C ++ 11) conversion operators that do not allow implicit conversions or copy-initialization ."

Now for those for whom I work, it is required that all our constructors be explicit. Being an old fart, I don’t like to change the coding style too much and forget about the T blah style ...

The question as such is: "Is there a way to make the constructor explicit by allowing copy initialization syntax?"

There are very good reasons to make the constructor explicit, and most of the time you do want to make it explicit.

In these cases, I thought I could do something along the line:

 class T { template<typename = V> T(const V&) = delete; T(const U&) { ... } } 

What will be the catch-all constructor that prohibits all conversions, but the one I really want.

I wonder if there is any trick that I could use.

thanks

Edit: fixed the typo as Matt McNabb pointed out. thanks

+6
source share
1 answer

T blah = U(); gives an error, because, as you correctly explain, copy-initialization causes an implicit conversion of U to T ; but you noted the explicit constructor. (Note: this is not a copy constructor)

An explicit conversion will look like T blah = T(U()); , and this should work without errors.

T blah(U()); is a function declaration (see the most annoying parsing ). You probably didn't actually try to use blah as if it were an object in your test case, otherwise you would notice this problem.


Turning to your question:

Is there a way to make the constructor explicit, allowing the copy initialization syntax?

No, as the exact text you indicated about explicit is explained:

Defines constructors [...] that do not allow copy-initialization [...].

You need to switch to direct or copied initialization. IMHO, which is still a good thing, copy-initialization is cumbersome and only good for avoiding MVP; but now that we can avoid MVP using force initialization, it is no longer needed at all.

You can use any of the following actions that work, because in all cases the T element is directly and explicitly initialized by the list element:

 T blah{ U() }; T blah = T{ U() }; // redundant copy/move operation, probably elided 

Note that T blah = { U() }; cannot be used here because this form of initialization (known as copy list initialization) cannot use an explicit constructor.

+3
source

Source: https://habr.com/ru/post/986471/


All Articles