C++11 - Wrong constructor called in GCC/Clang (not in VS 2013) - gcc

I have this code which works fine in VS 2013 but doesn't compile in either GCC 4.8 or clang 3.3!
AND_end(c)->next = new ListNode<Point>{ b->val };
The error message is the following: "cannot convert from "Point" to "int".
Now, gradually, member val of b is a Point:
struct Point
{
int x;
int y;
double distance(const Point& other) const
{
if (this == &other)
return 0.;
return std::sqrt(std::pow(other.y - y, 2.) + std::pow(other.x - x, 2.));
}
bool operator==(const Point& other)
{
return x == other.x && y == other.y;
}
bool operator!=(const Point& other)
{
return !(*this == other);
}
};
b is a Line:
using Line = ListNode<Point>*;
a ListNode is a typical node for a singly linked list:
template<typename T>
struct ListNode
{
T val; // Value
ListNode* next = nullptr; // Next node in the list
// Constructor: takes a value of type T and optionally a pointer to the next node
explicit ListNode(T v, ListNode* n = nullptr)
: val{ v }, next{ n }
{
// Empty body, both member variables are initialized already
}
};
So, the line of code that doesn't compile should do the following: create a new ListNode, with T = Point, by supplying to the explicit ListNode constructor its first (and only) argument T v, which is a Point (b->val is a Point). This argument will be copied into the ListNode member val by copy, using the default copy constructor.
What seems to happen in both GCC and clang is that b->val is supplied to the Point constructor, hence the error message above (and for the sake of completeness, and additional warning is given: "missing field 'y' initializer").
VC++12 seems to get it all right instead.
So, what's up? Am I missing anything obvious (maybe, happens from time to time) or is there a nasty problem here?

I think the problem is, you do not have copy constructor for Point, therefore, in this line,
explicit ListNode(T v, ListNode* n = nullptr)
: val{ v }, next{ n }
since there's no copy constructor, val{v} will try to initialize by aggregate.
From 8.5.1,
An aggregate is an array or a class (Clause 9) with no user-provided
constructors.
When an aggregate is initialized by an initializer list,
as specified in 8.5.4, the elements of the initializer list are taken
as initializers for the members of the aggregate, in increasing
subscript or member order. Each member is copy-initialized from the
corresponding initializer-clause.
For a point type, the aggregate initialization shall be val {v.x, v.y}.
Or, you can implement a copy constructor for Point class.
GCC & Clang are correct. VS is wrong and it should reject your code.

Related

std::map find fails when key is pointer

I am unable to get the std::map find to locate the correct row in the std::map. The key is a class pointer and I have created a struct (tdEcApplDataMapEq) to compare the class's binary arrays for a match.'
The problem is it doesn't work. I call FoEcApplData::operator== when the find starts. It says the first entry does not a match and then the find returns out pointing to the first item on the std::map list. There is no attempt by find to search the other map entries. Also the one match test failed (false), so why is find saying its a match?
This probably has something to do with the std::map declaration. std::map says the third argument is for std::less, but I am doing a == vs. <.
If I change it to do < the same this happens. It enters FoEcApplData::operator< which return a true on the first check and find search stops with the search pointing to the 1st entry in the list.
How do I get find() to use the custom struct for the search?
My example adds 10 rows to FdTEcApplDataMap. It copies the CDH_DISABLE_XACT182 class into hold for the search later. I then do the find() test using hold as the search key.
Inside entry1
Inside entry2
Inside entry3<== this is the one I am searching for
Inside entry4
Inside entry5
Inside entry6
Inside entry7
Inside entry8
Inside entry9
Inside entry10
Inside entry1
This is the find:
auto hazard = ExcludedCmdDict.find(&hold);
if(hazard != ExcludedCmdDict.end())
{
std::cout << "found it " << hazard->second << std::endl;
}
This is the compare function being used:
bool FoEcApplData::operator==( const FoEcApplData& FoEcApplDataObject) const {
if(myNumOfBytes <= FoEcApplDataObject.NumOfBytes())
{
const EcTOctet* temp;
temp = FoEcApplDataObject.Data() ;
for(EcTInt i = 0; i < myNumOfBytes ; i++)
{
if(myData[i] != temp[i])
{
return false ;
}
}
return true;
}
else // myNumOfBytes > FoEcApplDataObject.NumOfBytes()
{
const EcTOctet* temp;
temp = FoEcApplDataObject.Data() ;
for(EcTInt i = 0; i < FoEcApplDataObject.NumOfBytes(); i++)
{
if(myData[i] != temp[i])
{
return false ;
}
}
return true;
}
}
This is the declaration for the std::map.
/*
Custom less for find on the FdTEcApplDataMap.
Needed since we are using pointers.
Returns - true - match, false - no match
node - pointer to the item you are looking for
node2 - pointer to an item on the list
*/
struct tdEcApplDataMapEq {
bool operator()(FoEcApplData *const& node, FoEcApplData *const& node2) const
{
return *node == *node2;
}
};
typedef std::map< FoEcApplData *, std::string, tdEcApplDataMapEq> FdTEcApplDataMap;
std::map expects the compare function to work like std::less. You need to use something along the lines of:
struct tdEcApplDataMapEq {
bool operator()(FoEcApplData *const& node, FoEcApplData *const& node2) const
{
return (*node < *node2); // Implement operator<() function for FoEcApplData
}
};
While at it, change the name of the struct to reflect the fact that it is trying to compute "less than".
struct tdEcApplDataMapLess {
bool operator()(FoEcApplData *const& node, FoEcApplData *const& node2) const
{
return (*node < *node2); // Implement operator<() function for FoEcApplData
}
};

using a union-like class in an std::initializer_list

In the code below I show union-like class S which contains two non-related structs B and C. I show how to instantiate the non-POD std::string and delete it again and then switch S to S::CC and set the num int.
#include <vector>
#include <string>
#include <iostream>
#include <memory>
struct B
{
B() {}
~B() {}
std::string str;
void Func1() {}
};
struct C
{
C() {}
~C() {}
int num;
void Func2() {}
};
struct S
{
S() { tag = CC; }
S( const S& s )
{
switch( s.tag )
{
case BB:
new ( &b.str ) std::string;
b.str = s.b.str;
break;
case CC:
c.num = s.c.num;
default:
break;
}
}
~S()
{
switch( tag )
{
case BB:
b.str.~basic_string< char >();
break;
case CC:
c.num = 0;
break;
default:
break;
}
}
enum { BB, CC } tag;
union
{
B b;
C c;
};
};
struct H
{
H( std::initializer_list< S > initializerList ) : initListVect( initializerList ) {}
std::vector< S > initListVect;
};
int main()
{
S s;
s.tag = S::BB;
new ( &s.b.str ) std::string; // docs say use new placement to create memory
s.b.str = "bbb";
s.b.str.~basic_string< char >(); // string usage in B ok
s.tag = S::CC;
s.c.num = 333; // int usage in C ok
H h { }; // what should the init list be if I wanted 3 list elements S::BB, S::CC, S::BB?
return 0;
}
My goal, however, is to use S in an std::initializer_list. I don’t know what the format should be for initializeing h. What should the arguments be if I wanted to initialize h with these S::BB, S::CC, S::BB?
My compiler is VS2015.
Edit:
This post’s history: my posting comes from a need for a definitive answer to the question of storing compile-time-deduceable heterogeneous objects in an std::initializer_list. This question has been asked many times before and there have been many attempts at answers (see Heterogeneous containers in C++). The most simplistic answer is to use polymorphism, but this ignores the power of being able to define a type at compile time (templates). Besides, heterogeneous, non-related objects grouped together polymorphically means a lot of derived data members are useless, which sows usage and maintenance confusion downstream. Other advice given was to use boost::any or boost::variant, but this has the same weakness as polymorphism and reduces message declaration clarity. Another attempt at container object heterogeneity was the use of std::tuple, but although an initializer_list can certainly contain tuples, this approach too ignores compile-time type resolution. I even found a paper written in 1999 called Heterogeneous, Nested STL Containers in C++ which uses template template arguments to solve the heterogeneity problem. After all this, I settled on class-like unions which led to my posting here. Class-like unions for non-related/heterogeneous container objects has perfect message declaration clarity, no object size ambiguity, and is compile time template-able, and it leads to excellent downstream maintenance scenarios.
Edit2: (5 weeks later) Here is what has happened. 1) I implemented a full class-like union solution given the advice in this posting. The result was tedious and unwieldy with ‘tag’ being used to identify which sub-method to call for each new functionality. Low grade regarding code maintenance. 2) c++17 has accepted std::variant. Since that is currently not yet implemented in VS2015 Update 2, I set about using boost::variant. See What is the right c++ variant syntax for calling a member function set to a particular variant? which uses the Visitor pattern to allow access to initialized variant members and member functions. This eliminates the ‘tag’ switches and variant ‘get’ calls. Bottom line: I dropped my class-like union and adopted variant for creating maintainable code that uses initializer_list to store variant member functionality all being initializable at compile time (read: highly maintainable).
Alright, I'm feeling generous and I've made custom unions myself so he're some stuff that'll get you set up. I've rewritten your S structure to be more compliant and usable. (I've made changes marked by comments)
struct S
{
S() : tag(CC) // initializer
{
new (&c) C; // make C object
}
S(int num) : tag(CC) // added integer constructor
{
new (&c) C;
c.num = num;
}
S(const std::string& str) : tag(BB) // added string constructor
{
new (&b) B;
b.str = str;
}
S( const S& s ) : tag(s.tag)
{
if (tag == CC)
{
new (&c) C; // construct c
c.num = s.c.num;
}
else if (tag == BB)
{
new (&b) B; // construct b, not b.str
b.str = s.b.str;
}
}
S& operator= (const S& s) // added assignment operator
{
if (tag == s.tag) // just copy b or c
{
if (tag == CC)
c = s.c;
else
b = s.b;
}
else // reconstruct b or c
{
if (tag == CC)
{
c.~C(); // destroy c
new (&b) B; // construct b
b.str = s.b.str;
}
else
{
b.~B(); // destroy b
new (&c) C; // construct c
c.num = s.c.num;
}
tag = s.tag;
}
return *this;
}
~S()
{
if (tag == CC)
{
c.~C(); // destroy c
}
else if (tag == BB)
{
b.~B(); // destroy b, not b.str
}
}
enum { BB, CC } tag;
union
{
B b;
C c;
};
};
One of the things that you were doing improperly was skipping the construction and destruction of B and C and going straight for the internal variables. You should always create and destroy types properly even when they may be trivial. While this may work out, not initializing these objects properly is only asking for trouble (It also makes it easier should you change B or C in the future).
To make using the class easier, I added in the proper constructors for std::string and int as well as an assignment operator. Because now that we can construct the objects how we want, your main() could look like this:
int main()
{
S s; // default S
s = std::string("bbb"); // set to string
s = 333; // set to number
// use initialization list
H h { std::string("bb"), 33, std::string("bb") };
return 0;
}
I encourage you to modify B and C to use constructors to build their internals rather than relying on S.

Access inserted element from unordered_map::emplace return value

I'm calling unordered_map::emplace() and I am storing the returned value (a pair). I just want to access the inserted value from the pair but for the life of me I cannot figure out the correct configuration of this confusing pair.
My unordered map definition:
std::unordered_map<GUID, shared_ptr<Component>> components;
I've looked at the unordered_map::emplace() documentation; according to this the first element in the pair should be the shared_ptr<Component> but the compiler is just not happy.
In the below code I get the error: Error 2 error C2227: left of '->gUid' must point to class/struct/union/generic type
class Component {
public:
template<typename T, typename... Params>
GUID addComponent(Params... params)
{
auto cmp = Component::create<T>(params...);
auto res = components.emplace(cmp->gUid, cmp);
if (!res.second) {
GUID gUid;
getNullGUID(&gUid);
return gUid;
}
return (*res.first)->gUid; // compiler error here
// *Yes I know I can do: return cmp->gUid;
}
GUID gUid; // initialised in constructor
std::unordered_map<GUID, std::shared_ptr<Component>> components;
};
Any idea how to correctly access the pairs second value?
The first of the pair returned from emplace is an iterator -- which, for unordered_map, acts like a pointer to a pair<key, value>. So to get the value from that pair, you need second:
return res.first->second->gUid;

Singly Linked List using shared_ptr

I was trying to implement singly linked list using share_ptr. Here is the implementation...
Below is the node class...
template<typename T>
class Node
{
public:
T value;
shared_ptr<Node<T>> next;
Node() : value(0), next(nullptr){};
Node(T value) : value(value), next(nullptr){};
~Node() { cout << "In Destructor: " << value << endl; };
};
Below is the linked list class...
template<typename T>
class LinkedList
{
private:
size_t m_size;
shared_ptr<Node<T>> head;
shared_ptr<Node<T>> tail;
public:
LinkedList() : m_size(0), head(nullptr) {};
void push_front(T value)
{
shared_ptr<Node<T>> temp = head;
head = make_shared<Node<T>>(Node<T>(value));
head->next = temp;
m_size++;
if (m_size == 1)
tail = head;
}
void pop_front()
{
if (m_size != 0)
{
// Here I am having doubt------------------------!!!
//shared_ptr<Node<T>> temp = head;
head = head->next;
m_size--;
if (m_size == 0)
tail = nullptr;
}
}
bool empty()
{
return (m_size == 0) ? true : false;
}
T front()
{
if (m_size != 0)
return head->value;
}
};
My question is, am I using the shared_ptr properly for allocating a node? If not, how should I use the shared_ptr to allocate and how should I delete the node in the pop_front method?
I believe this belongs on code review.
Most importantly: Why are you using shared_ptr? shared_ptr means the ownership of an object is unclear. This is not the case for linked lists: Every node owns the next. You can express that using unique_ptr which is easier and more efficient.
pop_front seems to be functioning correctly. You may consider throwing an exception or an assertion instead of doing nothing when using pop_front on an empty list.
front is more problematic. If the list is empty you most likely get a garbage object.
What is the significance of tail? It does not seem to be used for anything and since you cannot go backwards there is no real point to getting the tail.
make_shared<Node<T>>(Node<T>(value)) should be make_shared<Node<T>>(value) instead. make_shared<Node<T>>(value) creates a Node using value as the parameter for the constructor. make_shared<Node<T>>(Node<T>(value)) creates a Node with value as the parameter and then creates a new Node with the temporary Node as parameter and then destroys the first Node.
You are missing the copy and move constructor and assignment and move assignment operators.
After you are satisfied with your list implementation consider using std::forward_list instead.

C++ STL priority_queue with struct Clearification

I have looked over this thread which talks about using this method for comparison:
struct thing
{
int a;
char b;
bool operator<(const thing &o) const
{
return a < o.a;
}
};
priority_queue<thing> pq;
On the other hand other uses method such as this:
struct Time {
int h;
int m;
int s;
};
class CompareTime {
public:
bool operator()(Time& t1, Time& t2) // Returns true if t1 is earlier than t2
{
if (t1.h < t2.h) return true;
if (t1.h == t2.h && t1.m < t2.m) return true;
if (t1.h == t2.h && t1.m == t2.m && t1.s < t2.s) return true;
return false;
}
}
priority_queue<Time, vector<Time>, CompareTime> pq;
While I logic myself with the first method, I don't quit understand the second method. Mostly because of the syntax. I am not quit sure what the overloading operator operator() means. What is that operator overloading?
Also, from cplusplus on priority_queue, I don't quite understand the following, mainly the second parameter.
template < class T, class Container = vector<T>,
class Compare = less<typename Container::value_type> > class priority_queue;
In another word, I don't understand the second method and its calling convention.
Also, what's the difference and which method is preferred?
I am not quit sure what the overloading operator operator() means.
What is that operator overloading?
What we have here is an overloading of the function call operator (see SO question) , this means that client code can 'treat' the CompareTime class instances as compare functions :
CompareTime ct;
if ( ct(t1, t2) )
{
...
}
I don't quite understand the following, mainly the second parameter.
The cplusplus reference summarizes quite well , the template parameters :
0 arg - The type of the objects within the queue.
1 arg - The underlying container/data structure for the queue, by
default its the std vector
2 arg - Operation on priority queue relies on some precedence
comparison, i.e. which item in the queue should be 'before' other item (see also Wikipedia , so this arg accepts to have compare object (functor) which mean instances of plain class which overload the () operator , the default is the std less functor which is simply a wrapper above the '<' semantics (boolean 2 valued function object).
// TEMPLATE STRUCT less
template<class _Ty>
struct less : public binary_function<_Ty, _Ty, bool>
{
// functor for operator<
bool operator()(const _Ty& _Left, const _Ty& _Right) const
{
// apply operator< to operands
return (_Left < _Right);
}
};

Resources