In my C++ class we are learning to use function objects and the like, but now we got a code snippet that works on teacher's compiler but not on ours (we use different OS's).
We tested the code snippet below with several compilers (MSVC, clang) and they all reject it, a bit minimized:
#include <functional>
struct Fraction {
Fraction();
Fraction(int z, int n);
Fraction(Fraction&);
// various data members
};
struct FractionComparator {
int operator()(Fraction a, Fraction b) {
return 1;
}
};
int main() {
std::function<int(Fraction, Fraction)> comparator = FractionComparator();
}
We get on clang on macOS:
No viable conversion from 'FractionComparator' to 'function<int (Fraction, Fraction)>'
We already found out that adding a move constructor solves the problem, but we have no idea why this difference exists and why this code doesn't compile on our compilers.
Any ideas?
Why does adding a move-constructor solve the problem?
Fraction is attempted to be copy-constructed from an rvalue.
But constuctor Fraction(Fraction&); takes a non-constant reference. Non-const references are not allowed to bind to temporaries.
The proper constructor signature should be:
Fraction(const Fraction&);
When you declare a move constructor compiler will move-construct Fraction from an rvalue instead.
Why doesn't this code compile on our compilers, but compiles on the teacher's?
This code compiles with VC++.
It looks like the compiler is not conforming to the standard here.
I could find this StackOverflow question with some more detail. It seems to be a compiler extension that allows this to compile.
If compiler extensions are disabled via /Za flag it will not compile anymore.
Starting from C++14 the constructor you are trying to use does not participate in overload resolution unless the target function is callable with the given set of arguments (with std::declval<>() arguments of given types). In your case that would be std::declval<Fraction>() arguments.
Your FractionComparator functor is not callable with std::declval<Fraction>() arguments since it receives its arguments by value, while temporary objects of type Fraction cannot be copied: Fraction's copy-constructor's argument is declared as a non-const reference.
Declare your copy constructor as
Fraction(const Fraction &);
and the code will compile. If you have a good reason to keep it as non-const, then you will have to explore other opportunities for making this work. Why does your FractionComparator insist on receiving its parameters by value anyway?
Your question is tagged C++11, but apparently your compiler is retroactively implementing this C++14 requirement even in C++11 mode.
Related
Came across an interesting issue today started by my own typo. I created a lambda that takes in a reference to a struct and incorrectly set it to a std::function that receives it's argument by value.
Here's a more concise version:
#include <functional>
struct InputStruct
{
int i;
InputStruct(): i(1){}
};
void function_rcv(std::function<bool(InputStruct)> & func_ref)
{
InputStruct in;
func_ref(in);
}
int main()
{
std::function<bool(InputStruct)> my_func = [](InputStruct & in)->bool{return in.i==1;};
function_rcv(my_func);
}
Checking with godbolt shows this compiles successfully with MSVC, but fails for both Clang and GCC.
Interestingly enough, using a primitive instead of a struct fails compilation on all three compilers.
Is this a bug in the MSVC compiler?
In summary: it is not a compiler bug. MSVC accepts this code because of its default non-conforming behavior, but it can be made standard-conforming with a switch.
First of all, I need to clarify std::function's one aspect: it accepts a function (in general, Callable) which signature is not a perfect match, but the parameters can be converted. Consider:
using intFn = void (int);
void fn(short);
intFn *a = fn; // doesn't compile
std::function<intFn> b = fn; // compiles!
Here, intFn a function type which has an int parameter, while the function fn has a short parameter. The simple function pointer a, cannot be set to point to fn, as the type of the parameter differ (int vs short). But, std::function allows this, so b can be set to point to fn.
In your example, std::function has an InputStruct parameter by value, while the lambda has a non-const lvalue reference InputStruct &. When std::function std::forwards its parameter, it becomes an xvalue, which cannot be bound to the lambda's lvalue reference parameter. That's why standard conforming compilers don't accept this code.
Why does MSVC accept this code? Because it has non-conforming behavior by default: it allows binding class temporaries (and xvalues) to non-const lvalue references. You can disable this behavior with /Zc:referenceBinding (or the older /Za option). If you use this switch, MSVC rejects your example.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
What are copy constructors?
Why do we use them? Is it necessary to call a destructor if we do?
What is a copy constructor?
Quoting the C++11 standard, §12.8/2:
“A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&,
volatile X& or const volatile X&, and either there are no other parameters or else all other parameters
have default arguments”
So there are 4 different forms. Of these the X const& form is the one most often used. This is also the form of the implicit copy constructor that is generated (if possible) if no copy constructor is declared for the class.
A copy constructor is used for copying an object to a new instance of the class. A default copy constructor performs a member-wise copy, which is different from and more safe than just copying the bits. In particular a copy constructor or move constructor is logically used for a copy initialization, an initialization using the = sign like
Some_type x = expression;
In some circumstances the compiler is allowed to assume that copying is all that a copy constructor does, regardless of what it actually does. Logically needless copy constructions can then be removed, or as the standard calls it, elided. For example, if the expression above is the number 42, then instead of using that argument to construct a temporary and copying or moving that to x, the argument may be used to initialize x directly.
However, even when that is done, so that the copy constructor is not used, if the copy constructor would have been used except for the optimization then a copy constructor must exist and be accessible.
C++11 §12.2/1:
“Even when the creation of the temporary object is unevaluated (Clause 5)
or otherwise avoided (12.8), all the semantic restrictions shall be respected as if the temporary object had
been created and later destroyed.”
Is it necessary to call a destructor?
Re “Is it necessary to call a destructor if we [use a copy constructor]? ”.
Generally no.
Destructors in C++ are called automatically when an object goes out of scope or when it's indirectly or directly destroyed via delete. The only exception is for placement new, which is a low level feature that has nothing in particular to do with copy constructors. Although placement new can involve copy construction.
A difference between C++03 and C++11 copy constructors.
To understand the difference between C++03 and C++11 regarding copy constructors you must be aware of three facts:
If a copy constructor isn’t declared, then it’s generated if possible. Hence by default every class has a copy constructor. It’s there.
Access is independent of overload resolution.
Overload resolution chooses between all member functions, regardless of whether they’re accessible or not. Then access is checked. At that point you may get an error message about calling an inaccessible function, despite an expectation that overload resolution ideally should choose only from the accessible functions…
An ordinary function (or just function) is a better match than a an instantiation of a function template with the same signature.
Here is an example of overloading resolution choosing a private member function, in spite of a public function that could be called:
File [access_versus_overload_resolution.cpp]
class C
{
public:
void foo( double );
void foo( int );
void bar( double );
private:
void bar( int );
};
int main()
{
C().foo( 42 ); // OK.
C().bar( 42 ); //! Uh oh, inaccessible.
}
And here is an example of an ordinary function trumping a template instantiation:
File [function_versus_template.cpp]
using One = char[1];
using Two = char[2];
auto foo( char const* ) -> One&;
auto foo( char const (&)[10] ) -> Two&;
auto bar( char const* ) -> One&;
template< int n >
auto bar( char const (&)[n] ) -> Two&;
#include <iostream>
auto main() -> int
{
using namespace std;
//cout << sizeof( foo( "Blah blah" ) ) << endl; //! Ambiguous
cout << sizeof( bar( "Blah blah" ) ) << endl; // "1"
}
With these facts at hand:
An inaccessible copy constructor will be chosen even if there is an accessible member function template that is just as good a match.
(As a logical consequence of the general overload resolution rules.)
In C++11, a member function template instantiation will therefore be chosen only if it is a better match than the copy constructor, if any.
But in C++03 there was a special rule that ensured that with a conforming compiler a function member template would never be used to copy an object.
Here’s the C++03 wording, §12.8/3 in that standard, where I’ve added suitable emphasis:
“A declaration of a constructor for a class X is ill-formed if its first parameter is of type (optionally cv-
qualified) X and either there are no other parameters or else all other parameters have default arguments. A
member function template is never instantiated to perform the copy of a class object to an object of its class
type.
while in C++11 the wording is subtly changed, in that standard’s §12.8/6, where again I’ve added suitable emphasis:
“A declaration of a constructor for a class Xis ill-formed if its first parameter is of type (optionally cv-qualified)
X and either there are no other parameters or else all other parameters have default arguments. A member
function template is never instantiated to produce such a constructor signature.”
I.e. no special injunction against function templates being used to copy objects in C++11.
Unfortunately for history buffs, the most readily available C++03 compiler for Windows, namely MinGW g++ of some old version such as 3.2, does not enforce the C++03 rule.
File [template_versus_cc.cpp]
class S
{
private:
S( S const& ); // No such.
public:
S() {}
template< class T >
S( T& ) {}
};
int main()
{
S sm;
S const sc;
S s1( sm ); // OK in C++11, template is better match.
S s2( sc ); //! Line 19. Copy constructor is selected, inaccessible.
}
Compiling with old g++:
[H:\dev\test\copy_construction]
> \bin\MinGW_3_1\bin\g++ --version | find "++"
g++ (GCC) 3.2.3 (mingw special 20030504-1)
[H:\dev\test\copy_construction]
> \bin\MinGW_3_1\bin\g++ -std=c++98 -pedantic template_versus_cc.cpp
template_versus_cc.cpp: In function `int main()':
template_versus_cc.cpp:4: `S::S(const S&)' is private
template_versus_cc.cpp:19: within this context
[H:\dev\test\copy_construction]
> _
By the C++03/C++98 rules the compiler should have flagged both copy initializations, at lines 18 and 19, but only flagged the latter, behaving as a C++11 compiler in this respect.
This is also what the more modern g++ 4.8.2 does, as well as Visual C++ 12.0. But a conforming C++03-compiler must diagnose both initializations.
Scott Meyers has written about this, citing two of the SO C++ Lounge dwellers as sources. Unfortunately the article yields the impressions that (1) it’s all about universal reference template arguments in C++11, and (2) there’s is no bug in g++. The former is wrong, as shown above, while the latter is literally correct. There was a bug, but as the standard has evolved, with C++11 the g++ behavior is now conforming…
Copy constructors are important for quite the same reasons as a regular constructor would be, and that is to properly initialize the constructed object. Construction is not always trivial, and it doesn't matter where do you take the data from and in what form - other object of the same class or a set of simpler arguments.
Therefore copy constructor is there to solve problems like initializing const fields, but also when you use pointers, to decide on ownership of the pointed resource. You may want to share, or duplicate the data.
I'm working on a legacy library that needs to be backwards compatible with C++03, but is also forward compatible to take advantage of C++11 features like move semantics and explicit casting.
So, is it possible to emulate explicit casting in C++03? I know obviously about the explicit bool (or "safe" bool) idiom - but that's only for casting to a boolean type. Is it possible to emulate a general explicit cast operator in C++03?
I checked around, and found a discussion about this in a book called "Imperfect C++ : Practical Solutions for Real-Life Programming".
In this book, they discuss some ideas about emulating an explicit cast in C++03 (the book was written before C++11). Ultimately, they recommend creating an explicit_cast<T> template. However, I don't like that solution because I want users to simply be able to use static_cast<T>, which works fine in C++11.
So, another solution was to force the compiler to do two conversions, which will disallow implicit conversions. An example of that would be something like:
class int_cast
{
public:
int_cast(const int& v) : m_value(v)
{ }
operator int() const
{
return m_value;
}
private:
int m_value;
};
struct Foo
{
Foo()
{
x = 10;
}
operator int_cast() const
{
return int_cast(x);
}
int x;
};
Here, a Foo should be explicitly convertible to int, but not implicitly. (This code is lifted almost verbatim from Imperfect C++, except in their example they are converting a custom Time object to a std::tm.
However, this doesn't actually work, at least not using GCC 4.7.2:
Foo f;
int x = static_cast<int>(f);
This results in :
test3.cpp: In function ‘int main()’:
test3.cpp:44:28: error: invalid static_cast from type ‘Foo’ to type ‘int’
So I guess "Imperfect C++" is wrong here. The compiler wasn't able to convert a Foo to an int, even with an explicit cast. (Maybe this worked on older compilers?) So, is there anyway to emulate this in C++03 (without using a custom cast operator)?
"Imperfect C++" is right, because it uses a custom "keyword" - actually a function name masquerading as a keyword (not unlike eg.: Tribool's indeterminate). If you try to static_cast you crash against the limitation that the language can only accept conversion chains that involve up to one user-defined type, whereas you have two conversions - from "Foo" to "int_cast" and from there to int.
If you want specifically to be able to static_cast then you'll probably have to hack something with macros to supersede normal static_cast... and accept to live in Undefined Behaviour Land. My preferred choice is to actually work in the inverse direction: simply use explicit_cast and use a macro to redefine it as a static_cast invocation when in C++11 mode. I use explicit cast in my C++ backports toolkit and thus in all the C++ code I write, and I have found no important issues so far.
I did a test here, but the output is a loop without ending, I don't know why.
Actually, I am doing another test, but when I wrote this, I don't understand how the loop occurred. It is output "ABC" repeatedly.
#include <map>
#include <string>
#include <iostream>
class test
{
public:
std::map <int, int> _b;
test();
test (std::map<int, int> & im);
~test();
};
test::test()
{
std::cout<<"abc";
_b.clear();
_b[1]=1;
test(_b);
}
test::test(std::map <int, int>& im)
{
std::cout<<im[1];
}
test::~test() {};
int main ()
{
test a;
}
The issue here is that the compiler interprets the statement
test(_b);
not as code that creates a temporary object of type test passing in parameter _b, but as a variable declaration for a variable named _b of type test, using the default constructor. Consequently, what looks like a piece of code that creates a temporary test object using the second constructor is instead recursively creating a new object of type test and invoking the constructor another time.
To fix this, you can give the variable an explicit name, such as
test t(_b);
This can only be interpreted as a variable of type test named t, initialized using the second constructor.
I have never seen this before, and I've been programming in C++ for years. Thanks for showing me yet another corner case of the language!
For an official explanation: According to the C++03 ISO spec, §6.8:
There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion (5.2.3) as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration.
(My emphasis). In other words, any time C++ could interpret a statement as either an expression (the temporary object cast) or as a declaration (of a variable), it will pick the declaration. The C++ spec explicitly gives
T(a);
As an example of a declaration, not a cast of a to something of type T.
This is C++'s Most Vexing Parse - what looks like an expression is instead getting interpreted as a declaration. I've seen the MVP before, but I have never seen it in this context.
the problem is from constructor you again calling the contructor test(_b)
test::test(){std::cout<<"abc";_b.clear();_b[1]=1;test(_b);}
here is what happens
everytime you call test(_b) it first calls default constructor test::test and it in turns calls the test(_b) and the loop goes on and on untill the stack overflows.
remove the test(_b) from the default constructor
I'm pretty sure that you are not actually "calling the constructor" since they are not directly callable IIRC. The legalese had to do with constructors not being named functions - I don't have a copy of the Standard handy or I might quote it. I believe what you are doing with test(_b) is creating an unnamed a temporary which invokes the default constructor again.
I'm not familiar with the particularities of the standard, but it may be that calling a constructor within a constructor is undefined. As such it could be compiler dependent. In this particular case it causes infinite recursion of your default constructor without ever calling your constructor with the map argument.
C++ FAQ 10.3 has an example with a constructor that has two parameters. If you add an int parameters to your second constructor such as test(map, int), it exhibits a somewhat normal behaviour.
For good form I would simply change test::test(std::map <int, int>& im) for test::testInit(std::map <int, int>& im), and test(_b) to testInit(_b).
This is a follow-on question to
C++0x rvalue references and temporaries
In the previous question, I asked how this code should work:
void f(const std::string &); //less efficient
void f(std::string &&); //more efficient
void g(const char * arg)
{
f(arg);
}
It seems that the move overload should probably be called because of the implicit temporary, and this happens in GCC but not MSVC (or the EDG front-end used in MSVC's Intellisense).
What about this code?
void f(std::string &&); //NB: No const string & overload supplied
void g1(const char * arg)
{
f(arg);
}
void g2(const std::string & arg)
{
f(arg);
}
It seems that, based on the answers to my previous question that function g1 is legal (and is accepted by GCC 4.3-4.5, but not by MSVC). However, GCC and MSVC both reject g2 because of clause 13.3.3.1.4/3, which prohibits lvalues from binding to rvalue ref arguments. I understand the rationale behind this - it is explained in N2831 "Fixing a safety problem with rvalue references". I also think that GCC is probably implementing this clause as intended by the authors of that paper, because the original patch to GCC was written by one of the authors (Doug Gregor).
However, I don't this is quite intuitive. To me, (a) a const string & is conceptually closer to a string && than a const char *, and (b) the compiler could create a temporary string in g2, as if it were written like this:
void g2(const std::string & arg)
{
f(std::string(arg));
}
Indeed, sometimes the copy constructor is considered to be an implicit conversion operator. Syntactically, this is suggested by the form of a copy constructor, and the standard even mentions this specifically in clause 13.3.3.1.2/4, where the copy constructor for derived-base conversions is given a higher conversion rank than other user-defined conversions:
A conversion of an expression of class type to the same class type is given Exact Match rank, and a conversion
of an expression of class type to a base class of that type is given Conversion rank, in spite of the fact that
a copy/move constructor (i.e., a user-defined conversion function) is called for those cases.
(I assume this is used when passing a derived class to a function like void h(Base), which takes a base class by value.)
Motivation
My motivation for asking this is something like the question asked in How to reduce redundant code when adding new c++0x rvalue reference operator overloads ("How to reduce redundant code when adding new c++0x rvalue reference operator overloads").
If you have a function that accepts a number of potentially-moveable arguments, and would move them if it can (e.g. a factory function/constructor: Object create_object(string, vector<string>, string) or the like), and want to move or copy each argument as appropriate, you quickly start writing a lot of code.
If the argument types are movable, then one could just write one version that accepts the arguments by value, as above. But if the arguments are (legacy) non-movable-but-swappable classes a la C++03, and you can't change them, then writing rvalue reference overloads is more efficient.
So if lvalues did bind to rvalues via an implicit copy, then you could write just one overload like create_object(legacy_string &&, legacy_vector<legacy_string> &&, legacy_string &&) and it would more or less work like providing all the combinations of rvalue/lvalue reference overloads - actual arguments that were lvalues would get copied and then bound to the arguments, actual arguments that were rvalues would get directly bound.
Clarification/edit: I realize this is virtually identical to accepting arguments by value for movable types, like C++0x std::string and std::vector (save for the number of times the move constructor is conceptually invoked). However, it is not identical for copyable, but non-movable types, which includes all C++03 classes with explicitly-defined copy constructors. Consider this example:
class legacy_string { legacy_string(const legacy_string &); }; //defined in a header somewhere; not modifiable.
void f(legacy_string s1, legacy_string s2); //A *new* (C++0x) function that wants to move from its arguments where possible, and avoid copying
void g() //A C++0x function as well
{
legacy_string x(/*initialization*/);
legacy_string y(/*initialization*/);
f(std::move(x), std::move(y));
}
If g calls f, then x and y would be copied - I don't see how the compiler can move them. If f were instead declared as taking legacy_string && arguments, it could avoid those copies where the caller explicitly invoked std::move on the arguments. I don't see how these are equivalent.
Questions
My questions are then:
Is this a valid interpretation of the standard? It seems that it's not the conventional or intended one, at any rate.
Does it make intuitive sense?
Is there a problem with this idea that I"m not seeing? It seems like you could get copies being quietly created when that's not exactly expected, but that's the status quo in places in C++03 anyway. Also, it would make some overloads viable when they're currently not, but I don't see it being a problem in practice.
Is this a significant enough improvement that it would be worth making e.g. an experimental patch for GCC?
What about this code?
void f(std::string &&); //NB: No const string & overload supplied
void g2(const std::string & arg)
{
f(arg);
}
...However, GCC and MSVC both reject g2 because of clause 13.3.3.1.4/3, which prohibits lvalues from binding to rvalue ref arguments. I understand the rationale behind this - it is explained in N2831 "Fixing a safety problem with rvalue references". I also think that GCC is probably implementing this clause as intended by the authors of that paper, because the original patch to GCC was written by one of the authors (Doug Gregor)....
No, that's only half of the reason why both compilers reject your code. The other reason is that you can't initialize a reference to non-const with an expression referring to a const object. So, even before N2831 this didn't work. There is simply no need for a conversion because a string is a already a string. It seems you want to use string&& like string. Then, simply write your function f so that it takes a string by value. If you want the compiler to create a temporary copy of a const string lvalue just so you can invoke a function taking a string&&, there wouldn't be a difference between taking the string by value or by rref, would it?
N2831 has little to do with this scenario.
If you have a function that accepts a number of potentially-moveable arguments, and would move them if it can (e.g. a factory function/constructor: Object create_object(string, vector, string) or the like), and want to move or copy each argument as appropriate, you quickly start writing a lot of code.
Not really. Why would you want to write a lot of code? There is little reason to clutter all your code with const&/&& overloads. You can still use a single function with a mix of pass-by-value and pass-by-ref-to-const -- depending on what you want to do with the parameters. As for factories, the idea is to use perfect forwarding:
template<class T, class... Args>
unique_ptr<T> make_unique(Args&&... args)
{
T* ptr = new T(std::forward<Args>(args)...);
return unique_ptr<T>(ptr);
}
...and all is well. A special template argument deduction rule helps differentiating between lvalue and rvalue arguments and std::forward allows you to create expressions with the same "value-ness" as the actual arguments had. So, if you write something like this:
string foo();
int main() {
auto ups = make_unique<string>(foo());
}
the string that foo returned is automatically moved to the heap.
So if lvalues did bind to rvalues via an implicit copy, then you could write just one overload like create_object(legacy_string &&, legacy_vector &&, legacy_string &&) and it would more or less work like providing all the combinations of rvalue/lvalue reference overloads...
Well, and it would be pretty much equivalent to a function taking the parameters by value. No kidding.
Is this a significant enough improvement that it would be worth making e.g. an experimental patch for GCC?
There's no improvement.
I don't quite see your point in this question. If you have a class that is movable, then you just need a T version:
struct A {
T t;
A(T t):t(move(t)) { }
};
And if the class is traditional but has an efficient swap you can write the swap version or you can fallback to the const T& way
struct A {
T t;
A(T t) { swap(this->t, t); }
};
Regarding the swap version, I would rather go with the const T& way instead of that swap. The main advantage of the swap technique is exception safety and is to move the copy closer to the caller so that it can optimize away copies of temporaries. But what do you have to save if you are just constructing the object anyway? And if the constructor is small, the compiler can look into it and can optimize away copies too.
struct A {
T t;
A(T const& t):t(t) { }
};
To me, it doesn't seem right to automatically convert a string lvalue to a rvalue copy of itself just to bind to a rvalue reference. An rvalue reference says it binds to rvalue. But if you try binding to an lvalue of the same type it better fails. Introducing hidden copies to allow that doesn't sound right to me, because when people see a X&& and you pass a X lvalue, I bet most will expect that there is no copy, and that binding is directly, if it works at all. Better fail out straight away so the user can fix his/her code.