I woud like to know what is the meanig of "ref" in a vector type definition.
I am new to C++ and on the piece of code I am stripping out to learn I found
vector<ref<StupidBug> > bugs;
where “StupidBug” is a class.
It doesn't compile in gcc/C++11 because "template argument ">" is invalid" but moving the “>” to the left, closer to the previous one still gives the same error
That confuses me and I don't know anymore where is the mistake.
The code is a few years old, could it be bad writing? Does "ref" belong to c++?
Is that a multivector? or a template?
The background info:
The whole is about inserting and moving "bugs" in grid and the vector holds the number of bugs and put them in a certain position.
Here the code, first I have a Stupidbug class
class StupidBug
{
public:
int x();
int y();
// member initialization list
StupidBug(GraphID_t i=-1): cellID(i) {}
void move();
void draw(const eco_string& canvas);
};
And the vector with the "ref" is in another class:
class Model: public Space
{
public:
urand u; //random generator for positions
int tstep; //timestep - updated each time moveBugs is called
int scale; //no. pixels used to represent bugs
vector<ref<StupidBug> > bugs;
addBugs(int nBugs);
void addBugs();
void moveBugs();
void draw(TCL_args args);
};
Thanks for any answer!
Yet another reason to stop using namespace std;
It's the function template std::ref<T>
vector<ref<StupidBug> > can't be compiled because std::vector expect a type (in fact 2 type but the other is defaulted) and you provided a function std::ref<StupidBug>
It's probably that your old project have another ref template and somehow, when compile with C++11, it choose std::ref instead of that template.
I am almost sure that it is a user-defined class similar to smart pointers that was designed to substitute standard class std::auto_ptr that can not be used with the class std::vector.
It is possible that this class uses a reference count of objects.
Now instead of
vector<ref<StupidBug> > bugs;
you can write for example
vector<std::unique_ptr<StupidBug> > bugs;
Pay attention to this record of two '>" symbols
vector<std::unique_ptr<StupidBug> > bugs;
^^^^
It means that the code was compiled according to the C++ 2003 Standard when there were not new smart pointers except std::auto_ptr that can not be used with vectors.
There was a problem in the old C++ Standard relative to std::auto_ptr. As result new smart pointers were introduced in the new C++ Standard like std::unique_ptr or std::shared_ptr that can be used along with std::vector and other standard containers.
This class was used because the code is old and the new Standard was not yet adopted with its new classes or maybe it has functionality that is absent in the Standard or more suitable for some class of tasks.
At that time for example Scott Meyers in his book More Effective C++ was showing how a smart pointer with a reference count can be written. This theme wss popular at that days of the C++ 2003 Standard.:)
It is evident that this has nothing common with the standard function std::ref that also was introduced in the C++ 2011 except its name.:)
When the code was written there was neither standard function std::ref.:)
Just look through the header where the class is defined.:)
Now according to the C++ Standard (D.10 auto_ptr)
The class template auto_ptr is deprecated. [ Note: The class template
unique_ptr (20.7.1) provides a better solution. —end note ]
Thus due to the new smart pointers introduced in the new C++ Standard it seems there is no need any more to use this user-defined class ref.
thanks to your answers I was able to fix the issue.
Actually the code is from 2006 and used the c++03 Standard
ref<StupidBug>
is a template used as a custom smart pointer with some extra fuctions and not the „std::ref“ function. It is defined in a header called „classdesc“
For some reason even if I am not using "using namespace std;" the compiler whats to use the „ref“ function instead of the template.
The workaround for me has been using
classdesc::ref<StupidBug>
being „classdesc“ where the original template lives.
Using the new samart pointers from C++11 ( shared_ptr ) didn't work either because of the extra functions of the original template.
I don't know who was more right if #Vlad from Moscow or #StoryTeller....
Related
I have this class :
#include <unordered_map>
class MyClass
{
// Trie node class
struct Node
{
std::unordered_map<char, Node> m_children;
// ...
}; // .....
};
int main()
{
MyClass m;
}
When compiling, I got this errors :
/usr/include/c++/7/bits/stl_pair.h:204:11: error: ‘std::pair<_T1,
_T2>::second’ has incomplete type
_T2 second; /// #c second is a copy of the second object
^~~~~~ AutocompleteModern.cpp:24:12: note: forward declaration of ‘struct Autocomplete::Node’
struct Node
^~~~
I know that if I use a pointer as a value in the hash map, this might work. But I wonder if it's possible to make the code above compile without changing the type the hash map's value. or is it impossible ?
You have a circular loop dependency: You say that m_children should contain Node objects, but at that point the class Node isn't defined (only declared).
You could use pointers (or references) to incomplete types though:
std::unordered_map<char, std::unique_ptr<Node>> m_children;
Note the use of std::unique_ptr, which is used to indicate that the map is the sole owner of the Node objects (and also has the added benefit of some automatic memory management).
It's possible for some containers, but std::unordered_map is not one of them. It might work with some implementations, but the standard doesn't require it to work for std::unordered_map (in fact it says its undefined to do it). So even if it compiled today, with a particular compiler, it might not work tomorrow.
The containers that can be declared with incomplete types are std::forward_list, std::list, and std::vector. So those containers can be used as a member of a class, before the class definition is complete)
But I wonder if it's possible to make the code above compile without changing the type the hash map's value. or is it impossible ?
It is impossible, because the compiler cannot compute a meaningful (and finite) sizeof for that MyClass.
Put yourself in the compiler shoes: it has to compute a layout, and a byte size (as given by sizeof) for MyClass quite early when compiling your code. And it obviously could not.
In C++, for such circularity, you have to use pointers (but you could "hide" them as smart pointers, etc.).
(So this answer is a rationale or an intuition for Some programmer dude's answer)
There is also another (purely "legal") reason: the C++11 standard n3337 forbids that. I leave up to you to check (and find precisely what clause there forbids that).
PS. As commented by songyanyo, you might find some particular C++ standard library implementation where your code is accepted (I guess that on such implementations, more hidden pointers are used). This is not the case on my Linux Debian Sid box (both with GCC 8 and Clang 7). In practice you want to write code that is compilable on your box. I have no idea which particular C++ standard library is the most conforming to the standard, but the intuition above stays.
I have a pretty simple code as the following.
template<typename T>
struct cell{
int nr;
T* someInfo;
};
template<typename T>
void doSomething(cell<T> c)
{
cout<<c.nr;
}
I actually have numerous functions using cells, very few using the T* template info (above code does not use it). Can I write my program (in C++98) without ending up with
countless template keywords, T* or cell stuff? I want to reduce clutter, to write a
rather C-like C++ code, easy to read by those who are not familiar with
C++. Can I make the compiler understand (without macros) that whenever it sees cell, it
is actually cell<T> and it has to put a template on the function?
If there is no C++98 solution, I prefer a C way using void* instead of T*. That comes with no clutter in the rest of the code, but I can't delete c.someInfo, but only
free(c.someInfo).
Reuse code by inheritance from a non-templated base class.
struct cell_base {
int nr;
};
template<typename T>
struct cell : cell_base {
T* someInfo;
};
void doSomething(cell_base const& c)
{
cout<<c.nr;
}
So whatever needs the non-templated bits accepts a cell_base, and the few things that do need the template parameter can be templates.
If you want to use templates, then you need to use the correct template syntax.
Which does indeed mean writing T quite a few times as well as template<typename T>. That's life: the compiler does some very clever things, and needs this "boilerplate" in order to disambiguate.
You can reduce the amount of typing by writing all the functions inline inside the class declaration.
Using (void*) instead would be anachronistic.
You can typedef your template; and which will completely hide the fact that it's a template for a specific type. ie
typedef cell<int> IntCell;
then usage of the type
void doSomething(const IntCell& c) {}
Edit: I now realize that you asked about c++98. My suggestion requires c++14 unfortunately.
You could use generic lambdas in place of template functions:
auto doSomething = [](auto c) {
cout<<c.nr;
}
If you're willing to wait for a bit, there is the concepts proposal for the C++ standard which will hopefully be included in C++20. It includes generic functions which could allow:
void doSomething(auto c)
{
cout<<c.nr;
}
Or
void doSomething(Concept c)
{
cout<<c.nr;
}
Where Concept is a concept that all cell<T> satisfy. This is a compile time analogue to the runtime inheritance suggested by StoryTeller.
Hoping this can be useful for somebody someday, I'll explain why I ended up with the
old-school C solution in C++. You maybe need to be in the same mess as me to understand,
i.e., you need to deal with some minor unknown pointer for which you do not want to clutter
a C++ code which already has many classes that can not be ported to C in reasonable time.
I thank all the responses I received, and after considering them, I regret they could not solve
my problems. Even with inheritance, I still end up with hundreds of template and <T>
stuff because I have many classes and sub-classes with cell members.
It is easier/cleaner to use void* someInfo as in C, as that does not require modifying all
classes that contain cells. The problem of deleting the void* pointer is left to the user
of the library. It's easy to allow/ask the user to make a unique call like
set_func_free_info(&custom_free_func). The deallocation function of the library could be:
if(func_free_info!=NULL)
func_free_info(c.someInfo);
else //don't let it get here if someInfo points to an object
free(c.someInfo); //needing a destructor, do use set_func_free_info(...).
Given some of the responses, I feel you :
might argue void* is "anachronistic". Maybe. If somebody told me that such an old language
like English is anachronistic faced to modern Esperanto, I would feel the same.
might say it is a bad idea to write code somehow for pure C programmers not familiar
with C++, in the line with a above remark ``the code ends up more complex than it needs to be
so even those who ARE familiar with C++ end up getting confused.''. If you honestly
think about this, here the opposite is true : the code is less complex by avoiding C++
features, as the template constructs would clutter all the code for a minor feature.
ask why don't stick to pure C and simply finish the story. I can't, because this is
part of a code where someInfo can be an object. So I end up
with the C-like C++ style that some here seem to hate, but you can really find reasons for it on
the linked material my comment above.
Anyway, M Stroustrup said that
C++ is deliberately designed to support a variety of
styles rather than a would-be "one true way".
So if you like to lecture about "your
true C++ way", you should understand you shouldn't do it. And you'll see life so much
more than a foolish game. C++ supports infinitely many more styles and possibilities than
C, e.g., I could use lambdas as in one of the replies, but too many would not understand it.
I would like to use something like typedef in my C++ programs to enhance type safety.
As an example, suppose I have two functions
void function1(unsigned idOfType1);
void function2(unsigned idOfType2);
then I can mistakenly pass idOfType2 to function1 and vice versa. I want the compiler to give me an error in this case. I am aware that I could wrap these unsigned in a struct, but then I'd have to give provide a field name and use . to access them, which is slightly inconvenient. Is there a good way around this?
Edit: As far as I know typedef will not work for this purpose as it is just a shorthand for a type and will not be used for type checking.
Use Boost strong typedef:
typedef creates an alias for an existing type. It does not create a new type that can be used for matching either function or template parameters...
Usage of BOOST_STRONG_TYPEDEF addresses this...
BOOST_STRONG_TYPEDEF is a macro which generates a class named "name" wraps and instance of its primitive type and provides appropriate conversion operators in order to make the new type substitutable for the one that it wraps.
As you say, a typedef won't help you here. I can't think of a better way immediately, however if you go with your wrapping in a struct/class option you could use a conversion operator to eliminate the member method or function call.
For example:
struct WrappedType
{
operator type()
{
return _value;
}
type _value;
}
I'm not saying this is the way to do it mind you ;-)
This is a late reply to an old question. But there are new developments on the C++ front and for the sake of completeness I'm adding this answer:
The opaque_typedef library is the author's attempt to provide most of the value of opaque typedefs through a library, without waiting for opaque typedefs to become a language feature.
The author of this library, Kyle Markley had a short brilliant speech at the cppcon 2015 introducing this library. The slides of his speech are on github the source code of the library is available on sourceforge. The library is header-only, written in C++11. Gcc and clang are ok, but VS2015 seems to have problems with it.
The use of the library is straight-forward. The following code was taken from the documentation. It creates an opaque typedef of int. It has the same interface as an int (it can be added, shifted, incremented, compared, etc.) but the arguments and return values are of the newly-created type, not of int:
#include "opaque/numeric_typedef.hpp"
struct myint : opaque::numeric_typedef<int, myint> {
using base = opaque::numeric_typedef<int, myint>;
using base::base;
};
There is a c++11 feature called enum class, which is basically a type safe enum. Maybe they can help here.
In foonathan's blog post from 2016 various approaches are covered, starting with an example class for simple cases:
class meter
{
public:
explicit meter(int val)
: value_(val) {}
explicit operator int() const noexcept
{
return value_;
}
private:
int value_;
};
and ending with a short template library with arithmetic support for custom type-safe types, allowing one to write this:
struct meter
: strong_typedef<meter, int>, addition<meter>
{
using strong_typedef::strong_typedef;
};
You can check the type in your function, so that if it didn't match, you can print an error or something.
You can use typeid to detect variable type, as follows:
typeid(*variablename*).name()
As suggested in one of the answers here, this is compiler-dependent and you have to use try-and-error method to find out which value works for you.
I read C++: auto_ptr + forward declaration? and its answers, especially the accepted one and I'm aware of the pitfalls when combining auto_ptr and forward declarated classes. But I'm encountering runtime problems with this same pattern that seems not to be covered by this Q&A (and all other auto_ptr-tagged Questions I checked).
When destroying my Outer-like class[1], I sometimes get an access violation, sometimes I only observe missing destructor calls.
// Outer.h - an example header
#include <uncopyable.h>
#include <memory>
class Inner;
class Outer: private Uncopyable
{
public:
Outer()
~Outer();
private:
std::auto_ptr<Inner> inner;
};
I'm implementing constructor and destructor in the cpp file and there the definition of the Inner type is present.
// Outer.cpp - an example implementation
#include "Outer.h" //< I use this include order to ensure compileability
#include "Inner.h" //< for units including Outer.h without preconditions
Outer::Outer(): inner(new Inner) {}
Outer::~Outer() {}
The described problems disappear if I:
include Inner.h within Outer.h or
explicitly calling inner.reset()
I work on legacy code that compiles only with C++-Builder 6, so I've to stick to std::auto_ptr since it's the only smart_ptr implementation the compiler seems to support, so there is (currently) no alternative to this type (that I know is deprecated by C++11).
My question: What am I doing wrong here, or is it maybe a well-known bug in BCB6[2]?
Additional Remark I expected that using auto_ptr on uncomplete types would be safe having read Herb Sutter's article Using auto_ptr Effectively, the section Wrapping Pointer Data Members deals with it. The problems I describe above are therefore a very confusing experience.
[1] This example is cut down to discuss the formal structure of auto_ptr usage.
[2] Borland C++ 5.6.4, and the STL shipped with C++-Builder 6 (upd4)
It's going to be easier to fix the code to compile on a newer compiler with unique_ptr support than to fix auto_ptr (Why do you think the Standard committee killed it completely? Because they considered it unfixable).
Why isn't std::initializer_list a core-language built-in?
It seems to me that it's quite an important feature of C++11 and yet it doesn't have its own reserved keyword (or something alike).
Instead, initializer_list it's just a template class from the standard library that has a special, implicit mapping from the new braced-init-list {...} syntax that's handled by the compiler.
At first thought, this solution is quite hacky.
Is this the way new additions to the C++ language will be now implemented: by implicit roles of some template classes and not by the core language?
Please consider these examples:
widget<int> w = {1,2,3}; //this is how we want to use a class
why was a new class chosen:
widget( std::initializer_list<T> init )
instead of using something similar to any of these ideas:
widget( T[] init, int length ) // (1)
widget( T... init ) // (2)
widget( std::vector<T> init ) // (3)
a classic array, you could probably add const here and there
three dots already exist in the language (var-args, now variadic templates), why not re-use the syntax (and make it feel built-in)
just an existing container, could add const and &
All of them are already a part of the language. I only wrote my 3 first ideas, I am sure that there are many other approaches.
There were already examples of "core" language features that returned types defined in the std namespace. typeid returns std::type_info and (stretching a point perhaps) sizeof returns std::size_t.
In the former case, you already need to include a standard header in order to use this so-called "core language" feature.
Now, for initializer lists it happens that no keyword is needed to generate the object, the syntax is context-sensitive curly braces. Aside from that it's the same as type_info. Personally I don't think the absence of a keyword makes it "more hacky". Slightly more surprising, perhaps, but remember that the objective was to allow the same braced-initializer syntax that was already allowed for aggregates.
So yes, you can probably expect more of this design principle in future:
if more occasions arise where it is possible to introduce new features without new keywords then the committee will take them.
if new features require complex types, then those types will be placed in std rather than as builtins.
Hence:
if a new feature requires a complex type and can be introduced without new keywords then you'll get what you have here, which is "core language" syntax with no new keywords and that uses library types from std.
What it comes down to, I think, is that there is no absolute division in C++ between the "core language" and the standard libraries. They're different chapters in the standard but each references the other, and it has always been so.
There is another approach in C++11, which is that lambdas introduce objects that have anonymous types generated by the compiler. Because they have no names they aren't in a namespace at all, certainly not in std. That's not a suitable approach for initializer lists, though, because you use the type name when you write the constructor that accepts one.
The C++ Standard Committee seems to prefer not to add new keywords, probably because that increases the risk of breaking existing code (legacy code could use that keyword as the name of a variable, a class, or whatever else).
Moreover, it seems to me that defining std::initializer_list as a templated container is quite an elegant choice: if it was a keyword, how would you access its underlying type? How would you iterate through it? You would need a bunch of new operators as well, and that would just force you to remember more names and more keywords to do the same things you can do with standard containers.
Treating an std::initializer_list as any other container gives you the opportunity of writing generic code that works with any of those things.
UPDATE:
Then why introduce a new type, instead of using some combination of existing? (from the comments)
To begin with, all others containers have methods for adding, removing, and emplacing elements, which are not desirable for a compiler-generated collection. The only exception is std::array<>, which wraps a fixed-size C-style array and would therefore remain the only reasonable candidate.
However, as Nicol Bolas correctly points out in the comments, another, fundamental difference between std::initializer_list and all other standard containers (including std::array<>) is that the latter ones have value semantics, while std::initializer_list has reference semantics. Copying an std::initializer_list, for instance, won't cause a copy of the elements it contains.
Moreover (once again, courtesy of Nicol Bolas), having a special container for brace-initialization lists allows overloading on the way the user is performing initialization.
This is nothing new. For example, for (i : some_container) relies on existence of specific methods or standalone functions in some_container class. C# even relies even more on its .NET libraries. Actually, I think, that this is quite an elegant solution, because you can make your classes compatible with some language structures without complicating language specification.
This is indeed nothing new and how many have pointed out, this practice was there in C++ and is there, say, in C#.
Andrei Alexandrescu has mentioned a good point about this though: You may think of it as a part of imaginary "core" namespace, then it'll make more sense.
So, it's actually something like: core::initializer_list, core::size_t, core::begin(), core::end() and so on. This is just an unfortunate coincidence that std namespace has some core language constructs inside it.
Not only can it work completely in the standard library. Inclusion into the standard library does not mean that the compiler can not play clever tricks.
While it may not be able to in all cases, it may very well say: this type is well known, or a simple type, lets ignore the initializer_list and just have a memory image of what the initialized value should be.
In other words int i {5}; can be equivalent to int i(5); or int i=5; or even intwrapper iw {5}; Where intwrapper is a simple wrapper class over an int with a trivial constructor taking an initializer_list
It's not part of the core language because it can be implemented entirely in the library, just line operator new and operator delete. What advantage would there be in making compilers more complicated to build it in?