I have the following map:
std::map<my_msgs::Nodelet, int> mRunningProcPID;
When trying to insert a new pair to the map I am getting the following error:
error: no match for ‘operator<’ (operand types are ‘const my_msgs::Nodelet_<std::allocator<void> >’ and ‘const my_msgs::Nodelet_<std::allocator<void> >’)
{ return __x < __y; }
I get it that I need to override the < operator for my_msgs::Nodelet, the problem is that I do not have access to that h file since it is being auto generated by ROS.
Any idea what can I do?
The problem is that std::map will attempt to index the mapped elements, and it doesn't know how to index my_msgs::Nodelet because it doesn't know how to compare this object.
You have to provide a third parameter when declaring this map, with a Compare function, or implement the necessary interface (handler for operator <) for it to use the default comparison method.
But you can also avoid this trouble by just using std::unordered_map instead.
std::unordered_map will do pretty much the same thing std::map does but it doesn't bother to index the elements. This approach is also considered faster in many cases.
Any idea what can I do?
Option 1: Use a non-member function to compare two Nodelet objects.
You can define a non-member function operator< between two Nodelet objects with the following signature.
bool operator<(my_msgs::Nodelet const& lhs, my_msgs::Nodelet const& rhs);
You don't need the ability to modify the class to do that. You can declare it in your own .h file and define it in your own .cpp file.
Option 2: Use a functor to compare two Nodelet objects
You can define a functor with the following interface:
struct CompareNodelet
{
bool operator()(my_msgs::Nodelet const& lhs, my_msgs::Nodelet const& rhs) const;
};
and use it to construct the map.
std::map<my_msgs::Nodelet, int, CompareNodelet> mRunningProcPID;
Related
I am implementing a command pattern implementations with large number of actions and parameters involved. To simplify I am planning to use class that can hold all possible params to module in a map.
class ParamBag {
public:
add(int paramId, shared_ptr<IParam> param);
bool contains(int paramId);
std::shared_ptr<IParam> get(paramId);
private:
int mask;
std::map<int, std::shared_ptr<IParam>> params;
};
One clear downside of this implementation is each param has to extend from IParam interface, can I somehow simplify this.
If the one that uses the param after the get knows the type of the param, then you can use c++17 std::any, or if you must use c++11 you can try boost::any, or if none of those you can resort back to a void*.
The difference is that void* will not fail on a cast to a wrong type, where any_cast would throw an exception, or return nullptr if used with a pointer. You would also need to use a custom deleter in the std::shared_ptr in order to be able to free the void*.
I have a wrapper class that needs to be used interchangeably with the wrapped class.
Fortunately the class and the wrapper are binary compatible (by design) and the conversion can be easily performed (for example in this case by reinterpret_cast, or even simpler as in the example).
In part, to achieve this, I need to be able to convert from the wrapper type to the wrapped type, via operator T().
Currently the code looks like this:
template<class T> // // I am putting this general T type, to show it can be a large (movable) object, for example, std::vector.
struct wrapper{
T a;
operator T const&() const&{return a;} // in other cases it can involve more code, like reinterpret_casts or some conditional blocks.
operator T&&() &&{return std::move(a);} // same
operator T&() &{return a;} // same
};
Can I condense these three conversion functions into one function or less code, or is there another way?
I could make it more general, (but longer code for this simple case) this way,
template<class T>
struct wrapper{
T a;
operator T const&() const&{return a;} // complicated code can be here only
operator T&&() &&{return std::move(operator A&());}
operator T&() &{return const_cast<T&>(operator T const&());}
};
The final objective is that T can be used interchangeably with wrapper<T>.
This is very similar to How do I remove code duplication between similar const and non-const member functions?,
however this case is more specific because 1) it involves the conversion operator and also, 2) involves l-value overloads.
Supposing one needs to obtain a logical value based on a
pack of template parameters, is there a reason to prefer an alias approach
vs a function approach?
Example:
template<bool...> struct bool_pack;
template<bool... bs>
using all_true = std::is_same<bool_pack<bs..., true>,
bool_pack<true, bs...>>;
as opposed to
template<class none=void>
constexpr bool all_true() { return true; }
template<bool First, bool... Rest>
constexpr bool all_true() {
return First and all_true<Rest...>();
}
Time required for compiling your example implementations
... should be measured, of course. That said, I have seen micro-benchmarks where the std::is_same approach leads to significantly shorter compile times; even compared to the C++17 fold expression (true && ... && bs) with the respective compilers. The recursive "function approach" you gave as an example should be clearly inferior in compile-time performance.
Note, however, that one could surely offer the most convenient interface by providing a wrapper around the most "efficient" (regarding compile-time effort) implementation.
Convenience in using the "interface"
Given these two choices, I would prefer the alias approach. If you need the result of that helper as a type (for inheritance, template-metaprogramming with specializations, or for tag dispatch), the alias yields cleaner syntax compared to, say, std::bool_constant<all_true_v<some_condition(), some_other_condition()>()>. In the other direction, it is simple to obtain a value of type bool from the alias: all_true<some_condition(), some_other_condition()>{} (relying on implicit type conversion).
Since C++14, yet another (fancy?) choice is to provide a value by a constexpr variable template which has either type std::true_type or std::false_type. By implicit conversion to bool it can readily be used where plain true or false is required, but it can also be passed as a function argument without losing its compile-time guarantee.
template<bool... bs>
constexpr auto all_true_c = typename std::is_same<
bool_pack<true, bs...>, bool_pack<bs..., true>
>::type{};
It may be a good strategy to follow the naming conventions used in the <type_traits> header of modern C++ providing both forms. If some utility is supposed to provide a value, one finds helper variable templates such as std::is_same_v:
template<class T, class U>
inline constexpr bool is_same_v = is_same<T, U>::value;// (since C++17)
if some helper is supposed to provide a type, one finds helper types such as std::decay_t:
template<class T>
using decay_t = typename decay<T>::type;// (since C++14)
... in addition to the conventional utilities without suffix, respectively.
I have a type A that's designed to be implicitly casted to type B. Here's an example case I'd like to use it in:
// Current implementation:
std::transform(vec_of_a.begin(), vec_of_a.end(), std::back_inserter(vec_of_b),
[](const A& a) -> B { return a; }); // Thanks, Kerrek SB.
// Ideal implementation - Won't compile, expected '(' after 'static_cast'.
std::transform(vec_of_a.begin(), vec_of_a.end(), std::back_inserter(vec_of_b),
static_cast<B>);
What can I do to make the latter option compile?
static_cast<B>, while it is invoked with function-call syntax cannot be passed like other callable things. E.g., there's no way to use & to get a function pointer to it.
You can use a short little lambda to achieve something similar to passing a function pointer to static_cast<B>, as you do in your current implementation:
std::transform(vec_of_a.begin(), vec_of_a.end(), std::back_inserter(vec_of_b),
[](const A& a) -> B { return a; });
Another option--in this particular case--would be to construct a vector<B> from the vector<A>:
std::vector<B> vec_of_b(vec_of_a.begin(), vec_of_a.end());
(This answer is a summary of the comments on both the question and bipll's answer.)
Build a functor enclosing static_cast:
template <typename T>
struct StaticCast
{
template <typename U>
T operator()(const U& rhs)
{
return static_cast<T>(rhs);
}
};
With this, you can call std::transform:
std::transform(vec_of_a.begin(), vec_of_a.end(), std::back_inserter(vec_of_b), StaticCast<b>());
It can be used in the case the output vector is already defined in place of the lambda shown in comments. If not, prefer the constructor mentioned in another answer**.
This functor version is compliant with C++98 if needed -- even if OP is tagged C++11, it may be worthy to note this point.
** Note that with this particular constructor, a warning C4244 is raised with VS compiler (tested with VS2017).
Yes, that's the way anonymous functions work in C++, and static_cast is not a function so you cannot pass its address as the mapped function. You'll have to deal with it.
You cannot use a constructor either.
I write a program with my class:
class COrder
{
public:
COrder();
~COrder();
public:
...
CList < CItem > m_oItem;
...
};
which suppose to have list od object of my other class:
class CItem
{
public:
CItem();
~CItem();
public:
int m_i;
double m_d;
CString m_o;
};
and compiler give me error like this in title. Any ideas why ?
In program I use COrder in map:
CMap <CString, LPCTSTR, COrder, COrder> m_map
Quote:
Add copy-constructor and assignment operator to your class COrder.
I add operator= to my class:
COrder& operator=( const COrder oNewOrder )
{
...
m_oItem.AddTail( oNewOrder.m_oItem.GetTail() );
...
return *this;
}
but what you mean by adding "copy-constructor" ?
http://msdn.microsoft.com/en-us/library/ccb3dh5c.aspx i found this but how to implement it in my code. i can't change CList class.
http://www.codeproject.com/Articles/13458/CMap-How-to
Add copy-constructor and assignment operator to your class COrder. This makes the class copyable.
[If class is used in as Key then you need HashKey() and CompareElemenst() in that class]
Also note that STL containers are superior to MFC containers.
You get an error because CMap has default copy-ctor but CMap and CList is derived from CObject and CObject declares private copy constructor and operator=.
So, CMap doesn't offer a copy semantic "out of the box".
I would suggest you to use STL std::map container, which is designed in a
way to implement copy semantic out-of-the-box.
What you don't have with STL out of the box is serialization only.
Note that std::map does not have the confusing ARG_KEY and ARG_VALUE
templates.
std::map just has the Key and Type template arguments (in its basic form).
http://msdn.microsoft.com/en-us/library/s44w4h2s%28VS.80%29.aspx
Or else you can go by the pointer way as Ajay suggested by which you will just shut up the compiler.
The problem statement:
CList<CItem> m_oItem;
And the trigger statement (or some usage):
CMap <CString, LPCTSTR, COrder, COrder> m_map;
Why? Well, CMap would call copy constructor and/or assignment operator for COrder. You didn't provide any, but compiler provides them from your class (i.e. for COrder). This class contains a CList object, which is inherited from CObject. CObject doesn't provide (or better say: Prevents) copy-constructor or assignment operator.
As a result, the compiler raises the error. Unfortunately, the (bad) compiler doesn't give you back-trace of this error.
Best bets for as the solution:
CList < CItem* > m_oItem;
CList<CItem> *m_poItem;
Use or implement your own collection.