Comparing std::pair<> first and last from equal_range - c++11

In the context of a map (template), for the following usage
auto begin = m_map.find(keyBegin);
auto end = m_map.find(keyEnd);
auto p = equal_range(begin,end,val);
if( !
(
p.first == p.second == m_map.end()
)
)
{
//do something
}
The type of keyBegin and keyEnd is unsigned int.
I get the following compilation error:
error: invalid operands to binary expression
('int' and 'iterator' (aka '__map_iterator<__tree_iterator<std::__1::
__value_type<unsigned int, char>, std::__1::__tree_node<std::__1::__value_type
<unsigned int, char>,
void *> *, long> >'))
p.first == p.second == m_map.end()
Can someone point out the cause of this error? I am of the understanding that the std::pair<> returned by std::equal_range<> has members of type ForwardIterator for first and second respectively.

Related

c++ : unordered map with pair of string_viewes

Here is a code snippet I have :
struct PairHasher {
size_t operator()(const std::pair<std::string_view, std::string_view>& stop_stop) const {
return hasher(stop_stop.first) + 37*hasher(stop_stop.second);
}
std::hash<std::string_view> hasher;
};
BOOST_FIXTURE_TEST_CASE(unordered_map_string_view_pair_must_be_ok, TestCaseStartStopMessager)
{
const std::vector<std::string> from_stops = {"from_0", "from_1", "from_2"};
const std::vector<std::string> to_stops = {"to_0", "to_1", "to_2"};
std::unordered_map<std::pair<std::string_view, std::string_view>, std::int32_t, TransportCatalogue::PairHasher> distance_between_stops;
for ( std::size_t idx = 0; idx < from_stops.size(); ++idx) {
std::cout << from_stops[idx] << " : " << to_stops[idx] << std::endl;
distance_between_stops[std::pair(from_stops[idx], to_stops[idx])] = idx;
}
std::cout << "MAP CONTENT :" << std::endl;
for (auto const& x : distance_between_stops)
{
std::cout << x.first.first << " : " << x.first.second << std::endl;
}
}
I expect to see 3 pairs inside the container, but there is only 1 concerning to the output :
MAP CONTENT :
from_2 : to_2
So, where are two more pair lost? What am I doing wrong?
Moving my comment to an answer.
This is pretty sneaky. I noticed in Compiler Explorer that changing:
distance_between_stops[std::pair(from_stops[idx], to_stops[idx])] = idx;
to
distance_between_stops[std::pair(std::string_view{from_stops[idx]}, std::string_view{to_stops[idx]})] = idx;
fixes the bug. This hints that the problem lies in some implicit string -> string_view conversion. And indeed that is the case, but it is hidden behind one extra layer.
std::pair(from_stops[idx], to_stops[idx]) creates a std::pair<std::string, std::string>, but distance_between_stops requires a std::pair<std::string_view, std::string_view>. When we insert values into the map, this conversion happens implicitly via overload #5 here:
template <class U1, class U2>
constexpr pair(pair<U1, U2>&& p);
Initializes first with std::forward<U1>(p.first) and second with std::forward<U2>(p.second).
This constructor participates in overload resolution if and only if std::is_constructible_v<first_type, U1&&> and std::is_constructible_v<second_type, U2&&> are both true.
This constructor is explicit if and only if std::is_convertible_v<U1&&, first_type> is false or std::is_convertible_v<U2&&, second_type> is false.
(For reference, std::is_constructible_v<std::string_view, std::string&&> and std::is_convertible_v<std::string&&, std::string_view> are both true, so we know this overload is viable and implicit.)
See the problem yet? When we use the map's operator[], it has to do an implicit conversion to create a key with the proper type. This implicit conversion constructs a pair of string_views that are viewing the temporary memory from the local pair of strings, not the underlying strings in the vector. In other words, it is conceptually similar to:
std::string_view foo(const std::string& s) {
std::string temp = s + " foo";
return temp;
}
int main() {
std::string_view sv = foo("hello");
std::cout << sv << "\n";
}
Clang emits a warning for this small example, but not OP's full example, which is unfortunate:
warning: address of stack memory associated with local variable 'temp' returned [-Wreturn-stack-address]
return temp;
^~~~

How do you perfectly hash a union of a possibly unicode char with a 32-bit integer?

I've never really had the need to create hash function before but right now it seems like the best solution for this.
I haven't tried anything, but I guess what I would try first is to hash take the unicode integer as the least significant 32-bits of a long. Then in the most significant 32-bits, store the integer.
struct Symbol
{
private:
enum Type {
Terminal,
Variable,
}
union {
char m_term;
int m_var;
}
Type m_type;
public:
this(char term) {
m_type = Type.Terminal;
m_term = term;
}
this(int var) {
m_type = Type.Variable;
m_var = var;
}
}
Symbol is the struct I'd like to hash. It contains a union which we should hash to achieve this. Was just wondering if my approach above is correct.
Thanks to commenters.
bool opEquals(Symbol sym) const {
if (m_type == Type.Terminal)
return m_term == sym.m_term;
else
return m_var == sym.m_var;
}
ulong toHash() {
ulong bit = m_type;
ulong key;
if (m_type == Type.Terminal)
key = cast(ulong) m_term;
else
key = m_var;
return bit | (key << 1);
}

How to compare enum in arduino?

I am facing an issue with arduino, since I want to change the state of my device using an enum, but it doesn't seeem to work, my code looks like below. I am not entirely sure where it goes wrong, I think as well that the comparison between settingTo and toP2P could be wrong?
Thanks in advance!
String toP2P = "503250"
String toABP = "414250";
String settingTo = LoRa_Tx.dataRX.substring(indx);
if( settingTo == toP2P ) {
//switching to P2P
Serial.println("current mode 1 "+(String) LoRa_Tx.current_modeRxTx);
if(LoRa_Tx.current_modeRxTx != LoRa_Tx.LoRaMod){
LoRa_Tx.current_modeRxTx = LoRa_Tx.LoRaMod;
}
} else if(settingTo == toABP){
//switching to ABP
if(LoRa_Tx.current_modeRxTx != LoRa_Tx.LoRaWan){
LoRa_Tx.current_modeRxTx = LoRa_Tx.LoRaWan;}
}
}
My class has the enum defined as
typedef enum modeRxTx{LoRaMod, LoRaWan, Idle} ;
modeRxTx current_modeRxTx = Idle;
In general, you should avoid the String class, as it will eventually cause problems. However, given that the LoRa_Tx appears to have a String member, here is one way to watch for those two modes:
if ((indx > -1) && (LoRa_Tx.dataRx.length() >= indx+5)) {
const char *settingTo = &LoRa_Tx.dataRx.c_str()[ indx ];
if ( strncmp_P( settingTo, PSTR("503250"), 6 ) == 0 ) {
//switching to P2P
Serial.print( F("current mode 1 ") ); // <-- saves RAM!
Serial.println( LoRa_Tx.current_modeRxTx );
if(LoRa_Tx.current_modeRxTx != LoRa_Tx.LoRaMod) {
LoRa_Tx.current_modeRxTx = LoRa_Tx.LoRaMod;
}
} else if ( strncmp_P( settingTo, PSTR("414250"), 6 ) == 0 ) {
//switching to ABP
if(LoRa_Tx.current_modeRxTx != LoRa_Tx.LoRaWan) {
LoRa_Tx.current_modeRxTx = LoRa_Tx.LoRaWan;
}
}
}
Instead of creating a substring, it just makes a pointer to the actual characters of data_Rx. The c_str() function returns a pointer to the first character (zero-based index) or the String, and the [ indx ] is the first of the mode number characters. Finally, the & is a pointer to the first mode number character.
Next, it uses a standard library function, strncmp_P (documented here), to compare those mode number characters with the modes you are looking for, and it only compares up to 6 characters. You don't say if there's a delimiter after "503250", so I don't know if "50325076" is possible and should be rejected.
The strncmp_P expects to get a PROGMEM string as the second argument, not just a const char *, so that's what the PSTR macro does. This saves RAM because the PSTR will be stored and compared from FLASH memory (aka PROGMEM). The Serial.print statements should use the F() macro for the same reason.

Accessing return by pointer out of function

I have the following function
std::tuple<int,val*>Socket::recv(val* values ) // const
{
char buf [ MAXRECV + 1 ];
memset ( buf, 0, MAXRECV + 1 );
int status = ::recv ( m_sock, buf, MAXRECV, 0 );
if ( status == -1 )
{
std::cout << "status == -1 errno == " << errno << " in Socket::recv\n";
// return std::make_tuple(0,NULL);//this is not working
}
else if ( status == 0 )
{
//return std::make_tuple(0,NULL); //this is not working
}
else
{
struct val* values=(struct val*) buf;
if(!std::isnan(values->val1) &&
!std::isnan(values->val2) &&
!std::isnan(values->val3) &&
!std::isnan(values->val4),
!std::isnan(values->val5),
!std::isnan(values->val6))
printf("received:%f %f %f %f %f %f\n", values->val1, values->val2,
values->val3, values->val4, values->val5, values->val6);
return std::make_tuple(status,values);
}
}
The received values are printed out in to standard output correctly within the function.
But when I try to access these received values out of the function by calling as follows what I get is all 0's.[after creating Socket rcvd object]
Would you tell me how to access these values outside the function?
1.
std::cout << std::get<1>(rcvd.recv(&values)->val1)
<< std::get<1>(rcvd.recv(&values)->val2)
<< std::get<1>(rcvd.recv(&values)->val3)
<< std::get<1>(rcvd.recv(&values)->val4)
<< std::get<1>(rcvd.recv(&values)->val5)
<< std::get<1>(rcvd.recv(&values)->val6)
<< std::endl;
2.
std::cout << std::get<1>(rcvd.recv(&values).val1)
<< std::get<1>(rcvd.recv(&values).val2)
<< std::get<1>(rcvd.recv(&values).val3)
<< std::get<1>(rcvd.recv(&values).val4)
<< std::get<1>(rcvd.recv(&values).val5)
<< std::get<1>(rcvd.recv(&values).val6)
<< std::endl;
3.
std::cout << std::get<1>(rcvd.recv(&values)[0])
<< std::get<1>(rcvd.recv(&values)[1])
<< std::get<1>(rcvd.recv(&values)[2])
<< std::get<1>(rcvd.recv(&values)[3])
<< std::get<1>(rcvd.recv(&values)[4])
<< std::get<1>(rcvd.recv(&values)[5])
<< std::endl;
where "values" comes from
struct val {
val1;
val2;
val3;
val4;
val5;
val6;} values;
All the three options of calling the function or access the struct val could not work for me.
Would you tell me
how to access these received values externally from any function?
how to return zero to struct pointer [NULL is not working ] when status is 0 or -1
Try
return std::make_tuple<int, val*>(0, nullptr);
The type of tuple is deduced from arguments, so by using 0,NULL you are actually using the null constant wich is evaluted to 0 and hence deduced type is <int,int>.
By the way, I see no reason for using NULL in C++11, if you need that really for some reason then cast NULL to val*
static_cast<val*>(NULL);
EDIT:
Other viable alternatives are
val* nullval = nullptr;
return std::make_tuple(0, nullval);
Or
return std::make_tuple(0, static_cast<val*>(nullptr));
Or (as comment suggest)
return {0, nullptr};
Choose the one that seems more clear to you.
You are lucky that the outside function is printing zeroes. It might have as well just dumped the core on you :)
What you are doing is accessing a buffer, that was created on a stack, after that stack was released (once the function's execution finished). That is HIGHLY UNSAFE and, pretty much, illegal.
Instead what you should do is allocate your data buffer in a 'free memory", using functions like malloc (in C) or operator new/new[] (in C++).
The quick fix is to replace the line
char buf [ MAXRECV + 1 ];
with
char * buf = new char [ MAXRECV + 1 ];
And when you do a type casting on line
struct val* values=(struct val*) buf;
you really ought to be sure that what you do is correct. If the sizeof() of you struct val is more than the sizeof(char[MAXRECV + 1]) you'll get in memory access troubles.
After you are done using the returned data buffer don't forget to release it with a call to free (in C) or delete/delete[] (in C++). Otherwise you'd have what is called a memory leak.

Get an unsigned int milliseconds out of chrono::duration

For a winapi wrapper I want to use chrono for a duration given to the call. The code example:
bool setTimer(std::chrono::duration<std::chrono::milliseconds> duration)
{
unsigned int dwDuration = Do some chrono magic here
SetTimer(m_hWnd,1,dwDuration,0);
}
dwDuration has to be in milliseconds.
First question: How do to the magic.
Second question: Is the parameter declaration okay?
The name of the type is std::chrono::milliseconds, and it has a member function count() that returns the number of those milliseconds:
bool setTimer(std::chrono::milliseconds duration)
{
unsigned int dwDuration = duration.count();
return std::cout << "dwDuration = " << dwDuration << '\n';
}
online demo: http://coliru.stacked-crooked.com/a/03f29d41e9bd260c
If you want to be ultra-pedantic, the return type of count() is std::chrono::milliseconds::rep
If you want to deal with fractional milliseconds, then the type would be std::chrono::duration<double, std::milli> (and the return type of count() is then double)
You can use the following code:
auto now = chrono::high_resolution_clock::now();
auto timeMillis = chrono::duration_cast<chrono::milliseconds>(now.time_since_epoch()).count();

Resources