- Define a function if not declared? - 6 Updates
- Polymorphism and std::copy - 3 Updates
- ifstream::open - 2 Updates
- Quick Question - 3 Updates
- begin and end as non-member functions - 4 Updates
- Ways to write initializations - 3 Updates
- faster than c - 1 Update
- Define a function if not declared? - 3 Updates
ram@zedat.fu-berlin.de (Stefan Ram): Apr 19 11:30PM Can one define a function only in the case that a function is not declared? For example, define »make_unique« at the top of a translation unit with lines that only have this effect when make_unique is not already declared at this point? |
ram@zedat.fu-berlin.de (Stefan Ram): Apr 20 12:45AM >On 4/19/2015 7:30 PM, Stefan Ram wrote: >>Can one define a function only in the case that a function >>is not declared? ... >What problem are you trying to solve? I want to write my code (e.g. for my tutorial) already in the C++14 style, e.g., using »::std::make_unique« instead of »::std::unique( new ...«. Some implementations do not already supply »make_unique«, so I thought about adding some lines at the top that define »make_unique« if it's not declared at this point. |
ram@zedat.fu-berlin.de (Stefan Ram): Apr 20 04:44PM >Subject: Quick Question You should use more specific subject lines in Usenet. |
ram@zedat.fu-berlin.de (Stefan Ram): Apr 20 04:49PM >The official definition of cin.get(cStr, n) is as follows: >std::istream::get >istream& get (char* s, streamsize n); That's a declaration, not a definition. >char someString[256]; >cin.get(someString, 255); >we ignore the return type istream&? You use the expression statement in the second line of the typed code given. This is the most fundamental statement in C++ taught at the beginning of beginner courses. The return type of »get« is not even consciously ignored in this case, it just doesn't matter. >What purpose does this return type serve? I assume that the return value is the target object. In this case, it would allow one to write cin.get( s, 255 ).get( s1, 255 ); . |
ram@zedat.fu-berlin.de (Stefan Ram): Apr 20 04:55PM >(according to www.cplusplus.com & www.cppreference.com): >void open (const char* filename, ios_base::openmode mode = ios_base::in); >void open (const string& filename, ios_base::openmode mode = ios_base::in); This is called a »declaration« or part of what is called a »synopsis«. >Why isn't the open member function that takes one parameter >part of the www.cplusplus.com std::ifstream::open definition? It /is/ there. Because the second parameter is declared with a default value, it can be omitted. It might help you to read a good textbook, such as »The C++ programming language, fourth edition« by Bjarne Stroustrup. |
ram@zedat.fu-berlin.de (Stefan Ram): Apr 20 10:24PM >Which methods (copy constructor, copy assignment operator,....) >must Carp and Tuna implement for the std::copy function to work >properly (to perform a deep copy on my vector)? If you want to use the "algorithm" "::std::copy", then it seems that you need to use a custom "smart pointer" class for your objects that deep-copies it pointees when copied. The following code shows a deep copy of a vector of pointers /without/ ::std::copy (not fully tested). #include <iostream> #include <ostream> #include <memory> #include <vector> struct Fish { virtual void print() = 0; virtual ::std::unique_ptr< Fish >clone() = 0; }; class Tuna : public Fish { void print () override { puts( "Tuna" ); } ::std::unique_ptr< Fish >clone () override { return ::std::make_unique< Tuna >( *this ); }}; class Carp : public Fish { void print () override { puts( "Carp" ); } ::std::unique_ptr< Fish >clone () override { return ::std::make_unique< Carp >( *this ); }}; int main() { ::std::vector< ::std::unique_ptr< Fish >> v; v.push_back( ::std::make_unique< Tuna >() ); v.push_back( ::std::make_unique< Carp >() ); ::std::vector< ::std::unique_ptr< Fish >> w; for( auto & f: v )w.push_back( f->clone() ); /* copying is here */ for( auto & f: w )f->print(); } |
Doug Mika <dougmmika@gmail.com>: Apr 20 01:58PM -0700 Hi I have a base class called Fish, from this base class I derive two classes called Tuna and Carp I create a vector<Fish> into which I place new objects of Tuna and Carp. ie vector<Fish> vecOfFish; vecOfFish.push_back(new Tuna()); vecOfFish.push_back(new Carp()); ... Now I want to create a second vector of Fish vector<Fish> vecOfFish2; and copy the first vector into the second using std::copy. Which methods (copy constructor, copy assignment operator,....) must Carp and Tuna implement for the std::copy function to work properly (to perform a deep copy on my vector)? |
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Apr 20 10:23PM +0100 On 20/04/2015 21:58, Doug Mika wrote: > I create a vector<Fish> into which I place new objects of Tuna and Carp. > ie > vector<Fish> vecOfFish; I think you meant vector<Fish*> but use vector<std::unique_ptr<Fish>> instead so you don't have to worry about memory leaks. > vector<Fish> vecOfFish2; > and copy the first vector into the second using std::copy. > Which methods (copy constructor, copy assignment operator,....) must Carp and Tuna implement for the std::copy function to work properly (to perform a deep copy on my vector)? A naked pointer doesn't have any methods so it is not possible using std::copy on the vector to do a "deep" copy; perhaps use std::transform instead sausages. /Flibble |
Paavo Helde <myfirstname@osa.pri.ee>: Apr 20 04:28PM -0500 Doug Mika <dougmmika@gmail.com> wrote in > vector<Fish> vecOfFish; > vecOfFish.push_back(new Tuna()); > vecOfFish.push_back(new Carp()); This does not compile. You have defined a vector of Fish objects, but are pushing in pointers to objects instead of objects. For getting polymorphic behavior you need a vector of some kind of pointers. Instead of plain pointers better consider some kind of smart pointers, e.g. vector<std::shared_ptr<Fish>> vecOfFish; vecOfFish.push_back(std::shared_ptr<Fish>(new Tuna())); vecOfFish.push_back(std::shared_ptr<Fish>(new Carp())); > Which methods (copy constructor, copy assignment operator,....) must > Carp and Tuna implement for the std::copy function to work properly > (to perform a deep copy on my vector)? For deep copy one needs to duplicate all the Tuna and Carp objects, given only pointers to Fish. One typically implements this by declaring a virtual clone function (look this up) in the base class. Both Carp and Tuna must implement this and return a (smart)pointer to the cloned object. The clone functions will typically make use of the copy constructors. std::copy() is probably not enough for getting deep copy (unless you use a specific deep-copying smartpointer which does not seem very practical otherwise). You will need to write a custom loop or use something like std::transform(). hth Paavo |
Doug Mika <dougmmika@gmail.com>: Apr 20 09:35AM -0700 The definition of std::ifstream::open is as follows (according to www.cplusplus.com & www.cppreference.com): void open (const char* filename, ios_base::openmode mode = ios_base::in); void open (const string& filename, ios_base::openmode mode = ios_base::in); this means that both the open member functions take two parameters. HOWEVER, I can open a stream as follows: ifstream inFile; inFile.open("input.dat"); Why isn't the open member function that takes one parameter part of the www.cplusplus.com std::ifstream::open definition? |
Victor Bazarov <v.bazarov@comcast.invalid>: Apr 20 12:52PM -0400 On 4/20/2015 12:35 PM, Doug Mika wrote: > ifstream inFile; > inFile.open("input.dat"); > Why isn't the open member function that takes one parameter part of the www.cplusplus.com std::ifstream::open definition? Read up on default argument values. V -- I do not respond to top-posted replies, please don't ask |
Doug Mika <dougmmika@gmail.com>: Apr 20 08:55AM -0700 The official definition of cin.get(cStr, n) is as follows: std::istream::get istream& get (char* s, streamsize n); Does this mean that when we type char someString[256]; cin.get(someString, 255); we ignore the return type istream&? Does this mean I could write: cin = cin.get(someString,255); What purpose does this return type serve? |
Victor Bazarov <v.bazarov@comcast.invalid>: Apr 20 12:16PM -0400 On 4/20/2015 11:55 AM, Doug Mika wrote: > Does this mean I could write: > cin = cin.get(someString,255); > What purpose does this return type serve? The purpose is to allow chaining of function calls, like cin.get(blah).get(blahblah) or using it in an expression cin.get(blah) >> somethingelse; V -- I do not respond to top-posted replies, please don't ask |
Paavo Helde <myfirstname@osa.pri.ee>: Apr 20 11:21AM -0500 Doug Mika <dougmmika@gmail.com> wrote in news:2cab1a66-64b1-4b2f-b46d- > Does this mean I could write: > cin = cin.get(someString,255); > What purpose does this return type serve? This allows for call chaining, e.g. cin.get(string1, 255).get(string2, 255).get(string3, 255); |
Paul <pepstein5@gmail.com>: Apr 20 05:53AM -0700 Please can someone explain why the second version does not compile even though the first one does? The error is "no matching function for call to end(int*&)" Thank you, Paul void testBeginEnd() { int a[] = {1, 2}; auto n = end(a) - begin(a); } void testBeginEnd(int a[] ) { auto n = end(a) - begin(a); } |
Luca Risolia <luca.risolia@linux-projects.org>: Apr 20 03:07PM +0200 On 20/04/2015 14:53, Paul wrote: > Please can someone explain why the second version does not compile even though the first one does? The error is "no matching function for call to end(int*&)" because the array parameter "decays" into a pointer, for which there is no matching end() function declared. |
Juha Nieminen <nospam@thanks.invalid>: Apr 20 02:30PM > int a[] = {1, 2}; > auto n = end(a) - begin(a); > } Here 'a' is a static array, not a pointer. Thus std::begin() and std::end() work fine with it. > { > auto n = end(a) - begin(a); > } Here 'a' is a pointer, not a static array, thus they don't work with it. The syntax you used doesn't mean "static array". It means "pointer". To receive a static array as parameter you have to use a different syntax: void testBeginEnd(int (&a)[2]) (Although note that the entire array is not passed to the function, but rather a reference to the original array.) --- news://freenews.netfront.net/ - complaints: news@netfront.net --- |
Victor Bazarov <v.bazarov@comcast.invalid>: Apr 20 10:45AM -0400 On 4/20/2015 10:30 AM, Juha Nieminen wrote: > void testBeginEnd(int (&a)[2]) > (Although note that the entire array is not passed to the function, > but rather a reference to the original array.) Just a nit-pick... Neither in the former example, nor in the latter declaration, the array is *static*. While severely overloaded, the term 'static' has nonetheless specific meaning that doesn't apply here, I think. It is better to use the term "an array of a known dimension" instead of "static array" in such explanations. In a declaration "foo(int a[])" the argument is "an array of unknown dimension", which inturnally (a pun on "in turn", he-he) is converted into a pointer, as you already pointed out. V -- I do not respond to top-posted replies, please don't ask |
peter koch <peter.koch.larsen@gmail.com>: Apr 20 01:44AM -0700 Søndag den 19. april 2015 kl. 01.31.38 UTC+2 skrev Victor Bazarov: > On 4/18/2015 4:02 PM, Stefan Ram wrote: [...] > rather than > T x{expression}; > For built-in types those mean the same thing. Not quite. Consider: int i = 3.14; int i = { 3.14 }; The first one succeeds, where the second one gives a compiler error. /Peter |
Victor Bazarov <v.bazarov@comcast.invalid>: Apr 20 09:03AM -0400 On 4/20/2015 4:44 AM, peter koch wrote: > int i = 3.14; > int i = { 3.14 }; > The first one succeeds, where the second one gives a compiler error. I am not sure why you have combined the two forms in the latter statement and expect it to work. Shouldn't the comparison have been int i = 3.14; with int i{3.14}; ? V -- I do not respond to top-posted replies, please don't ask |
peter koch <peter.koch.larsen@gmail.com>: Apr 20 07:14AM -0700 Mandag den 20. april 2015 kl. 15.03.36 UTC+2 skrev Victor Bazarov: > On 4/20/2015 4:44 AM, peter koch wrote: [snip] > int i = 3.14; > with > int i{3.14}; Yup - you are right. The equal-sign was the result of an incorrect copy-paste. /Peter |
Ian Collins <ian-news@hotmail.com>: Apr 20 07:52PM +1200 Paavo Helde wrote: > other temporary object [...]" > So, as the array is temporary, a pointer to its element can and will > become dangling as far as I can see. I thought the clarification (making the return value a constexpr) takes care of that. Certainly the generated code I've checked for a couple of compilers shows the values being accessed from static data. For example gcc -O3 -std=c++11 (or -O3 -std=c++14) compiles int c(); int f() { const int* y = std::begin({ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); return y[c()]; } as _Z1fv: pushl %ebp movl %esp, %ebp subl $8, %esp call _Z1cv movl ._0(,%eax,4), %eax leave ret where ._0 is ._0: .long 1 .long 2 .long 3 .long 4 .long 5 .long 6 .long 7 .long 8 .long 9 .long 10 and int f() { const int* y = std::begin({ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); return y[4]; } as _Z1fv: movl $5, %eax ret :) -- Ian Collins |
Victor Bazarov <v.bazarov@comcast.invalid>: Apr 19 08:36PM -0400 On 4/19/2015 7:30 PM, Stefan Ram wrote: > For example, define »make_unique« at the top of a > translation unit with lines that only have this effect > when make_unique is not already declared at this point? There is probably a way to do it using SFINAE, by trying to take the address of that function. If the function is not declared, taking the address of it should be not possible, so the template is not going to be generated... Then you could try to define your function as the member of that template, or specialize it... Seems like a lot of work for no obvious gain, though. What problem are you trying to solve? V -- I do not respond to top-posted replies, please don't ask |
Louis Krupp <lkrupp@nospam.pssw.com.invalid>: Apr 19 07:56PM -0600 On 19 Apr 2015 23:30:54 GMT, ram@zedat.fu-berlin.de (Stefan Ram) wrote: > For example, define »make_unique« at the top of a > translation unit with lines that only have this effect > when make_unique is not already declared at this point? If you can depend on only C++14 implementations having make_unique, then this page might be useful: http://sourceforge.net/p/predef/wiki/Standards/ Louis |
Paavo Helde <myfirstname@osa.pri.ee>: Apr 20 12:46AM -0500 ram@zedat.fu-berlin.de (Stefan Ram) wrote in news:make_unique- > Some implementations do not already supply »make_unique«, > so I thought about adding some lines at the top that define > »make_unique« if it's not declared at this point. This is typically done by a lot of preprocessor hackery. Here is a small excerpt from such a hackery, meant for defining std::move when it is not present. Such a mechanism provides a way to cope also with other mising features, not only missing function definitions. #ifdef __GNUC__ #define HAVE_COMPILER_GCC
Subscribe to:
Post Comments (Atom)
|
No comments:
Post a Comment