I have this code and this outputs the following:
link to the following example
https://godbolt.org/z/z8Pn9GsTv
template <typename T>
struct A1 {
A1() {
std::cout << "construction of a1" << std::endl;
}
~A1() {
std::cout << "destruction of a1" << std::endl;
}
~A1() requires (std::is_same_v<T,int>) {
std::cout << "it is an int" << std::endl;
}
};
int main() {
A1 <int>a;
return 0;
}
output:
construction of a1
destruction of a1
but swapping places of destructors it gives other result:
link to the code
https://godbolt.org/z/vxj7dPqaj
template <typename T>
struct A1 {
A1() {
std::cout << "construction of a1" << std::endl;
}
~A1() requires (std::is_same_v<T,int>) {
std::cout << "it is an int" << std::endl;
}
~A1() {
std::cout << "destruction of a1" << std::endl;
}
};
output:
construction of a1
it is an int
wondering is this a bug?
That's indeed a reported Clang bug1, as noted by Quimby.
Note that the second snippet (the one with the the constrained destructor first) doesn't really "work" in Clang, which just ignores the second destructor2.
Also note that, unlike gcc, at the moment I'm writing, Clang doesn't seem to have implemented [P0848R3] (which is about conditional trivial special member functions) yet3.
1) https://bugs.llvm.org/show_bug.cgi?id=50570
2) See e.g.: https://godbolt.org/z/rff7qfK65
3) See the reported values of the feature test macro __cpp_concepts, e.g. here: https://godbolt.org/z/P4z3Pj5vT
In your 2'nd code,
Try changing this:
A1 <int>a;
To this:
A1 <double>a;
And you'll get the output:
construction of a1
destruction of a1 // With MSVC & GCC compiler
My interpretation here is that when the condition for the first constructor (with requires) fails, the 2'nd constructor is called which prints "destruction of a1" and destroys a.
Here is a more detailed explanation...
On your class template, you have two destructors definition recipe. During instantiation the The compiler gets the "first" recipe that match the signature needed. Depending the compiler depending the result. I think clang, gcc and mingw will provide the same result, msvc approach is different. Better pattern for partial specialization disambiguation precedence chain?
Related
While porting some C++ code from Microsoft Visual Studio to gcc, I ran into a weird bug, which I eventually boiled down to this:
#include <iostream>
using namespace std;
class Foo {
public:
int data;
Foo(int i) : data(i)
{
cout << "Foo constructed with " << i << endl;
}
Foo(const Foo& f) : data(f.data)
{
cout << "copy ctor " << endl;
}
Foo(const Foo&& f) : data(f.data)
{
cout << "move ctor" << endl;
}
~Foo()
{
cout << "Foo destructed with " << data << endl;
}
};
int Bar(Foo f)
{
cout << "f.data = " << f.data << endl;
return f.data * 2;
}
int main()
{
Foo f1(10);
Foo f2(Bar(std::move(f1)));
}
If I compile and run the above code with Microsoft Visual Studio 2015 Community, I get the following output:
Foo constructed with 10
move ctor
f.data = 10
Foo destructed with 10
Foo constructed with 20
Foo destructed with 20
Foo destructed with 10
However, if I compile and run the code with gcc 6.1.1 and --std=c++14, I get this output:
Foo constructed with 10
move ctor
f.data = 10
Foo constructed with 20
Foo destructed with 10
Foo destructed with 20
Foo destructed with 10
gcc calls the destructor of f, the argument to Bar(), after Bar() returns, while msvc calls the destructor (apparently) before it returns, or at least before the constructor of f2. When is f supposed to be destructed, according to the C++ standard?
They are all right; it depends. It seems underspecified in the standard.
From [expr.call]/4 (this wording goes back to C++98);
The lifetime of a parameter ends when the function in which it is defined returns. The initialization and destruction of each parameter occurs within the context of the calling function.
And the CWG#1880;
WG decided to make it unspecified whether parameter objects are destroyed immediately following the call or at the end of the full-expression to which the call belongs.
Both the behaviour of g++ (and clang) and MSVC would be correct, implementations are free to pick one approach over the other.
That all said, if the code you have is dependent on this ordering, I would change it such that the ordering is more deterministic - as you have seen, it leads to subtle bugs.
A simplified example of this behaviour is;
#include <iostream>
struct Arg {
Arg() {std::cout << 'c';}
~Arg() {std::cout << 'd';}
Arg(Arg const&) {std::cout << 'a';}
Arg(Arg&&) {std::cout << 'b';}
Arg& operator=(Arg const&) {std::cout << 'e'; return *this;}
Arg& operator=(Arg&&) {std::cout << 'f'; return *this;}
};
void func(Arg) {}
int main() {
(func(Arg{}), std::cout << 'X');
std::cout << std::endl;
}
Clang and g++ both produce cXd and MSVC produces cdX.
This question already has answers here:
Why is value taking setter member functions not recommended in Herb Sutter's CppCon 2014 talk (Back to Basics: Modern C++ Style)?
(4 answers)
Closed 7 years ago.
Assume I have the following class, which has a method set_value. Which implementation is better?
class S {
public:
// a set_value method
private:
Some_type value;
};
Pass by value, then move
void S::set_value(Some_type value)
{
this->value = std::move(value);
}
Define two overloaded methods
void S::set_value(const Some_type& value)
{
this->value = value;
}
void S::set_value(Some_type&& value)
{
this->value = std::move(value);
}
The first approach requires definition of one method only while the second requires two.
However, the first approach seems to be less efficient:
Copy/Move constructor for the parameter depending on the argument passed
Move assignment
Destructor for the parameter
While for the second approach, only one assignment operation is performed.
Copy/Move assignment depending on which overloaded method is called
So, which implementation is better? Or does it matter at all?
And one more question: Is the following code equivalent to the two overloaded methods in the second approach?
template <class T>
void S::set_value(T&& value)
{
this->value = std::forward<T>(value);
}
The compiler is free to elide (optimise away) the copy even if there would be side effects in doing so. As a result, passing by value and moving the result actually gives you all of the performance benefits of the two-method solution while giving you only one code path to maintain. You should absolutely prefer to pass by value.
here's an example to prove it:
#include <iostream>
struct XYZ {
XYZ() { std::cout << "constructed" << std::endl; }
XYZ(const XYZ&) {
std::cout << "copy constructed" << std::endl;
}
XYZ(XYZ&&) noexcept {
try {
std::cout << "move constructed" << std::endl;
}
catch(...) {
}
}
XYZ& operator=(const XYZ&) {
std::cout << "assigned" << std::endl;
return *this;
}
XYZ& operator=(XYZ&&) {
std::cout << "move-assigned" << std::endl;
return *this;
}
};
struct holder {
holder(XYZ xyz) : _xyz(std::move(xyz)) {}
void set_value(XYZ xyz) { _xyz = std::move(xyz); }
void set_value_by_const_ref(const XYZ& xyz) { _xyz = xyz; }
XYZ _xyz;
};
using namespace std;
auto main() -> int
{
cout << "** create named source for later use **" << endl;
XYZ xyz2{};
cout << "\n**initial construction**" << std::endl;
holder h { XYZ() };
cout << "\n**set_value()**" << endl;
h.set_value(XYZ());
cout << "\n**set_value_by_const_ref() with nameless temporary**" << endl;
h.set_value_by_const_ref(XYZ());
cout << "\n**set_value() with named source**" << endl;
h.set_value(xyz2);
cout << "\n**set_value_by_const_ref() with named source**" << endl;
h.set_value_by_const_ref(xyz2);
return 0;
}
expected output:
** create named source for later use **
constructed
**initial construction**
constructed
move constructed
**set_value()**
constructed
move-assigned
**set_value_by_const_ref() with nameless temporary**
constructed
assigned
**set_value() with named source**
copy constructed
move-assigned
**set_value_by_const_ref() with named source**
assigned
note the absence of any redundant copies in the copy/move versions but the redundant copy-assignment when calling set_value_by_const_ref() with nameless temporary. I note the apparent efficiency gain of the final case. I would argue that (a) it's a corner case in reality and (b) the optimiser can take care of it.
my command line:
c++ -o move -std=c++1y -stdlib=libc++ -O3 move.cpp
I see the C++11 documentation (http://en.cppreference.com/w/cpp/language/lambda) for lambda expressions states capture by value and reference are supported but not rvalue reference. The closest SO question I could find related to this is: How to capture a unique_ptr into a lambda expression?, but it seems like my use case doesn't require the use of std::bind.
Code
#include <iostream>
#include <memory>
class Foo
{
public:
explicit Foo(int value = 0) : mValue(value) {}
// The following items are provided just to be explicit
Foo(Foo &&other) = default;
Foo &operator=(Foo &&other) = default;
Foo(const Foo &other) = delete;
Foo &operator=(const Foo &other) = delete;
~Foo() {}
int mValue;
};
void bar(std::unique_ptr<Foo> f)
{
std::cout << "bar: " << std::dec << f->mValue << "\n";
}
int main()
{
{
std::unique_ptr<Foo> f(new Foo(22));
std::cout << "main: " << std::hex << f.get() << "\n";
// Call the bar function directly (requires using std::move)
bar(std::move(f));
std::cout << "main: " << std::hex << f.get() << "\n";
}
{
std::unique_ptr<Foo> f(new Foo(99));
std::cout << "main: " << std::hex << f.get() << "\n";
// Lamda expression captures 'f' by reference and then calls the bar function (again, requires using std::move)
auto fn = [&f](){ bar(std::move(f)); };
fn(); // Execute the closure
std::cout << "main: " << std::hex << f.get() << "\n";
}
return 0;
}
Example Output
main: 0x92e010
bar: 22
main: 0
main: 0x92e010
bar: 99
main: 0
By examining the output it appears this program is running correctly (i.e., the observed results are what I expected. However, I have the following questions.
Questions
Is using the closure equivalent to the code that calls the bar function directly?
I'm asking explicitly since the documentation (see beginning of the question) about lambda expressions didn't state anything about using std::move on captured references (i.e., I want to make sure this doesn't run afoul of undefined behavior or similar bad outcomes).
If the answer to the first question is "you can't use std::move on the captured reference", then what is the right way to do this (e.g., the std::bind solution, etc)?
Is using the closure equivalent to the code that calls the bar function directly?
Yes, they're equivalent in this code. Captured references aren't special in any way that I can think of: you have fully defined behavior, as long as f is in scope and can be moved from.
In this response, tloveless pointed out that it's possible in MSVC to use this->foo::foo(42); for constructor delegation to directly call a constructor:
#include <iostream>
struct foo
{
int m;
foo(int p) : m(p) { std::cout << "foo("<<p<<")\n"; }
foo()
: m(0)
{
this->foo::foo(42);
std::cout << "foo(), " << m << "\n";
}
};
int main()
{
foo f;
std::cin.ignore();
}
I was surprised that this even compiles in MSVC; clang++, g++ and me agree it's illegal, e.g. [class.ctor]/2 "Because constructors do not have names, they are
never found during name lookup"
However, MSVC doesn't even emit a warning with /Wall and without language extensions /Za in MSVC12 Update 1 (2013) and MSVC10 SP1 (2010).
The output is:
foo(42)
foo(), 42
in both versions. So there's no temporary created, but a constructor called.
Questions:
What is the name of this extension?
Isn't it considered an extension? (/Za and the list of extensions don't seem to think so)
Is there some documentation for / official description of this feature?
(I tagged this question with the [delegating-constructors] tag since it reminds me heavily of this feature)
meta-info: I'm almost sure this question is a duplicate, since this feature is somewhat known. For example, see this answer to a "similar question". Please do not hesitate closing this as a dup if you can find an answer that describes this feature.
It is not constructor delegating. Try following code:
#include <iostream>
class C{
public:
C() { std::cout << "C" << std::endl; }
~C() { std::cout << "~C" << std::endl; }
};
struct foo
{
int m;
C c;
foo(int p) : m(p) { std::cout << "foo("<<p<<")\n"; }
foo()
: m(0)
{
this->foo::foo(42);
std::cout << "foo(), " << m << "\n";
}
};
int main()
{
foo f;
}
According to output field "c" is initialized twice but destroyed only once. As zneak noted, It is similar to new (this) foo(42).
In the following code the line that creates nested object prints only "constructor" with gcc, but not with VS 2013:
#include <iostream>
using namespace std;
struct test {
test() { cout << "constructor" << endl; }
test(const test&) { cout << "copy constructor" << endl; }
test(test&&) { cout << "move constructor" << endl; }
~test() { cout << "destructor" << endl; }
};
struct nested {
test t;
// nested() {}
};
auto main() -> int {
// prints "constructor", "copy constructor" and "destructor"
auto n = nested{};
cout << endl;
return 0;
}
Output:
constructor
copy constructor
destructor
destructor
So I guess what happening here is that a temporary object gets copied into n. There is no compiler-generated move constructor, so that's why it's not a move.
I'd like to know if this is a bug or an acceptable behaviour? And why adding a default constructor prevents a copy here?
It's not auto that's the problem; the following will exhibit the same:
nested n = nested{};
The temporary is being direct-initialized with {}, and then n is being copy-initialized with that, because test is a class-type (in this case, has user-defined constructor).
An implementation is permitted to directly initialize the ultimate target (n), but isn't obligated to, so either is legal.
Lots (really, lots) of details in 8.5 and 8.5.1 of the Standard.
This is a failure of MSVC to do copy elision (I'd guess related to the brace-init-constructor). It's perfectly legal both ways.