Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

for_each not returning (boolean) value

Tags:

c++

c++11

I have a program to verify if an IPv4 address entered as string is in valid dotted-quad notation.

The problem I am facing is that I'm not able to return (exit) function once I detect error. As per cppreference documentation for_each returns UnaryFunction. I tried using any_of and all_of but they require me using an loop (range-based loop) inside my lambda function which I'm trying to avoid. Am I missing something or it is not possible to return value in for_each.

vector<string> ipExplode;
string ip;
bool    inValidIp = false;
cout << "Server IP : ";
cin >> ip;
trim(ip);
ipExplode = explode(ip, '.');
if(not for_each(ipExplode.begin(), ipExplode.end(), [](const string& str) -> bool{
    int32_t ipNum;
    if(regex_search(str, regex("\\D+")))
        return false;
    try
    {
        ipNum = stoi(str);
        if(ipNum < 0 or ipNum > 255)
            return false;
    }
    catch (std::exception& ex)
    {
        return false;
    }
}))
    return false;
like image 716
Dark Sorrow Avatar asked Feb 28 '18 12:02

Dark Sorrow


2 Answers

from for_each:

If f returns a result, the result is ignored.

i.e. there is no point in returning a value from your for_each lambda.

A good choice here is all_of, which accepts a UnaryPredicate rather than a UnaryFunction, since you want to make sure that all of the parts of the string pass the lambda successfully:

bool isValid = std::all_of(ipExplode.begin(), ipExplode.end(), [](const std::string& str) -> bool{
    if(regex_search(str, regex("\\D+")))
        return false;
    try
    {
        int32_t ipNum = stoi(str);
        if(ipNum < 0 or ipNum > 255)
            return false;
    }
    catch (std::exception& ex)
    {
        return false;
    }
    return true;
});

all_of will stop iterating once an invalid part is found.

like image 125
Rotem Avatar answered Nov 18 '22 15:11

Rotem


Am I missing something or it is not possible to return value in for_each.

for_each does return the UnaryFunction. But if you put a unary function to if expression, its meaningless.

In your case, a lambda without capturing can implicitly convert to a function pointer. A non-null function pointer as a boolean value is always true. Thus your

if(not for_each( /* ... */ ))

will be evaluated to false all the time.

As commentators and other answerers have already written, std::all_of is what you want here.

like image 1
llllllllll Avatar answered Nov 18 '22 16:11

llllllllll