I am unable to understand why does following function not compile
#include <iostream>
#include <map>
int main(){
std::map<int, int, std::less<int>> myMap(std::less<int>());
myMap[2] = 2;
std::cout << myMap[2] << std::endl;
return 0;
}
The error message is as follows -
std_less_check.cpp: In function ‘int main()’:
std_less_check.cpp:6:10: warning: pointer to a function used in arithmetic [-Wpointer-arith]
myMap[2] = 2;
^
std_less_check.cpp:6:14: error: assignment of read-only location ‘*(myMap + 2)’
myMap[2] = 2;
^
std_less_check.cpp:6:14: error: cannot convert ‘int’ to ‘std::map<int, int, std::less<int> >(std::less<int> (*)())’ in assignment
std_less_check.cpp:7:23: warning: pointer to a function used in arithmetic [-Wpointer-arith]
std::cout << myMap[2] << std::endl;
while following compiles successfully
#include <iostream>
#include <map>
int main(){
std::map<int, int, std::less<int>> myMap(std::less<int>{});
myMap[2] = 2;
std::cout << myMap[2] << std::endl;
return 0;
}
Could someone please help me with this?
In the first program, you have a vexing parse. If the compiler can parse a declaration as either a variable or a function, it will choose to parse it as a function.
myMap can be parsed as a function declaration.
It returns a std::map<int, int, std::less<int>>.
It takes an argument of type std::less<int>(), which is itself a function type that returns a std::less<int> and takes no arguments. Note that you can't actually have a function type as an argument; the type is actually a pointer to a function that takes no arguments and returns a std::less<int>.
In the second program, replacing () with {} resolves the ambiguity. Now myMap can no longer be a function declaration, and so it instead declares a variable of type std::map<int, int, std::less<int>>.
Related
I would like to create a C++ script that uses map to execute heterogeneous functions, and stores the input/output in a map.
To deal with the heterogeneity I though to use the any type.
However, this creates problems, since the function pointer is not able to convert other type in any type.
Here is a minimal example that is not working, but illustrates what I would like to do:
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <map>
#include <any>
using namespace std;
string funct1(int a, int b)
{
int c= a+b;
string name = to_string(c);
return name ;
}
float funct2(int a, int b)
{
// float b2
float c=a-b;
return c ;
}
int main(void)
{
cout << "START" << endl;
std::map<std::string, std::any> ListObjIn; //
std::map<std::string, std::any> ListObjOut; //
typedef std::any (*FnPtr)(std::any, int);
std::map<std::string, FnPtr> ListCommand; //
//
ListObjIn["a1"] = 1;
ListObjIn["a2"] = 1.5;
ListCommand["do1"]= funct1;
ListCommand["do2"]= funct2;
// ListObjOut["res1"]= ListCommand["do1"]( std::any_cast<int>(ListObjIn["a1"]), 2);
ListObjOut["res1"]= ListCommand["do1"]( ListObjIn["a1"], 2);
cout << "RESULT 1=" << std::any_cast<string>(ListObjOut["res1"]) << endl;
ListObjOut["res2"]= ListCommand["do2"]( ListObjIn["a2"], 2);
cout << "RESULT 2=" << std::any_cast<string>(ListObjOut["res2"]) << endl;
cout << "END" << endl;
return(0);
}
I get the following error:
g++ -std=c++17 ./test.cpp
./test.cpp: In function ‘int main()’:
./test.cpp:34:24: error: invalid conversion from ‘std::__cxx11::string (*)(int, int) {aka std::__cxx11::basic_string<char> (*)(int, int)}’ to ‘std::map<std::__cxx11::basic_string<char>, std::any (*)(std::any, int)>::mapped_type {aka std::any (*)(std::any, int)}’ [-fpermissive]
ListCommand["do1"]= funct1;
^~~~~~
./test.cpp:35:24: error: invalid conversion from ‘float (*)(int, int)’ to ‘std::map<std::__cxx11::basic_string<char>, std::any (*)(std::any, int)>::mapped_type {aka std::any (*)(std::any, int)}’ [-fpermissive]
ListCommand["do2"]= funct2;
^~~~~~
I tried to change the input and output type of the function (ie string and float) to any, but this creates problems of conversion at other places.
So it is possible to have something very close to my original example, keeping the heterogeneity of type in/out and map of functions ? Or should think to workaround ? if so, which one ?
You should probably generify return type with std::any:
https://godbolt.org/z/G1EhqY
#include <iostream>
#include <variant>
using namespace std;
int main()
{
variant<int, float> var{0.23};
if(holds_alternative<float>(var)){
if(var.index() == 1){
cout << get<float>(var) << endl;
}
}
return 0;
}
The initialization should work but instead it gives the following error:
main.cpp: In function 'int main()':
main.cpp:7:33: error: no matching function for call to 'std::variant<int, float>::variant()'
I'm not sure if I made a mistake in the code.
0.23 is double. You should use 0.23f, which is float, instead.
The initialization failed because of the narrowing conversion inside the curly braces. so use
variant<int, float> var{0.23f};
instead.
Note that 0.23 is a double literal, not a float one.
See demo
I'm trying to adapt an example from Stroustrup C++ 4th Ed Page 1182, to call a function from operator()() vs the bind. Unfortunately, I'm getting a number of compilation errors. The code that worked before is // commented out. Does anyone know how to resolve the errors?
#include <iostream>
#include <random>
#include <map>
#include <functional>
using namespace std;
class rand_int {
public:
rand_int(int lo, int hi) : p{lo,hi}, re{rd()} {}
// int operator()() const { return r(); }
int operator()() const { return
uniform_int_distribution<>{p}(re); }
private:
uniform_int_distribution<>::param_type p;
random_device rd;
default_random_engine re;
// function<int()> r = bind(uniform_int_distribution<>{p}, re);
};
int main()
{
map<int,int> m;
rand_int ri{0,9};
for (int i=0; i < 100; ++i) {
m[ri()]++;
}
for (map<int,int>::iterator it = m.begin();
it != m.end(); ++it)
cout << it->first << ", " << it->second << '\n';
return 0;
}
Compilation:
clang++ -Wall -std=c++11 -pedantic test252.cc && ./a.out
In file included from test252.cc:2:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/random:49:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/random.h:35:
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/uniform_int_dist.h:243:25: error:
no matching function for call to object of type 'const
std::linear_congruential_engine<unsigned long, 16807, 0, 2147483647>'
__ret = __uctype(__urng()) - __urngmin;
^~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/uniform_int_dist.h:166:24: note:
in instantiation of function template specialization
'std::uniform_int_distribution<int>::operator()<const
std::linear_congruential_engine<unsigned long, 16807, 0, 2147483647> >'
requested here
{ return this->operator()(__urng, _M_param); }
^
test252.cc:12:35: note: in instantiation of function template specialization
'std::uniform_int_distribution<int>::operator()<const
std::linear_congruential_engine<unsigned long, 16807, 0, 2147483647> >'
requested here
uniform_int_distribution<>{p}(re); }
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/random.h:323:7: note:
candidate function not viable: 'this' argument has type 'const
std::linear_congruential_engine<unsigned long, 16807, 0, 2147483647>', but
method is not marked const
operator()()
^
This line:
uniform_int_distribution<>{p}(re);
modifies the member re. So the operator() can't be marked const.
You need to do:
int operator()() { // non-const method
return uniform_int_distribution<>{p}(re);
}
Here's a demo.
I want to get pointer to boost::any::operator=, so i did this:
bool(__thiscall boost::any::*func)(const bool&) = &(boost::any::operator=<bool>);
but now, compiler says
initializing' : cannot convert from 'overloaded-function' to 'bool (__thiscall boost::any::* )(const bool &)'
None of the functions with this name in scope match the target type
i also tried to make it this way:
bool(__thiscall boost::any::*func)(const bool&) = static_cast<(boost::any::*)(const bool&)>(&(boost::any::operator=<bool>));
but there is compiler says: "syntax error : '('" in this line
can anybody helps me, please?
P.S. I make instaces of boost::any in the code above
You can not specify the arguments in the assignment of the member function pointer.
This will do it:
#include <iostream>
#include <boost/any.hpp>
int main() {
boost::any any = false;
std::cout << boost::any_cast<bool>(any) << std::endl;
typedef boost::any& (boost::any::*assign_operator)(const bool&);
assign_operator assign = &boost::any::operator =;
(any.*assign)(true);
std::cout << boost::any_cast<bool>(any) << std::endl;
return 0;
}
I am trying to get the following code to compile using g++ 4.2.1 and am receiving the following errors
CODE:
#include <iostream>
#include <queue>
using namespace std;
int main (int argc, char * const argv[])
{
queue<int> myqueue();
for(int i = 0; i < 10; i++)
myqueue.push(i);
cout << myqueue.size();
return 0;
}
ERRORS:
main.cpp: In function ‘int main(int, char* const*)’:
main.cpp:10: error: request for member ‘push’ in ‘myqueue’, which is of non-class type ‘std::queue<int, std::deque<int, std::allocator<int> > > ()()’
main.cpp:12: error: request for member ‘size’ in ‘myqueue’, which is of non-class type ‘std::queue<int, std::deque<int, std::allocator<int> > > ()()’
Any ideas as to why? I tried in Eclipse, X-Code and through the terminal.
C++ FAQ Lite § 10.2
Is there any difference between List x; and List x();?
A big difference!
Suppose that List is the name of some class. Then function f() declares a local List object called x:
void f()
{
List x; // Local object named x (of class List)
...
}
But function g() declares a function called x() that returns a List:
void g()
{
List x(); // Function named x (that returns a List)
...
}
Replace queue<int> myqueue(); by queue<int> myqueue; and you'll be fine.