Boost function map to string - c++

I am trying to map a string to a function. The function should get a const char* passed in. I am wondering why I keep getting the error that
*no match for call to ‘(boost::_bi::bind_t<boost::_bi::unspecified, void (*)(const char*), boost::_bi::list0>) (const char*)’*
My code is below
#include <map>
#include <string>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>
typedef boost::function<void(const char*)> fun_t;
typedef std::map<std::string, fun_t> funs_t;
void $A(const char *msg)
{
std::cout<<"hello $A";
}
int main(int argc, char **argv)
{
std::string p = "hello";
funs_t f;
f["$A"] = boost::bind($A);
f["$A"](p.c_str());
return 0;
}

In your example, using boost::bind is completely superfluous. You can just assign the function itself (it will converted to a pointer to a function, and be type erased by boost::function just fine).
Since you do bind, it's not enough to just pass the function. You need to give boost::bind the argument when binding, or specify a placeholder if you want to have the bound object forward something to your function. You can see it in the error message, that's what boost::_bi::list0 is there for.
So to resolve it:
f["$A"] = boost::bind($A, _1);
Or the simpler
f["$A"] = $A;
Also, as I noted to you in the comment, I suggest you avoid identifiers which are not standard. A $ isn't a valid token in an identifier according to the C++ standard. Some implementations may support it, but not all are required to.

Related

Create a type which exhibits exact same behavior as STL container std::set

I have following typedefs :
typedef std::pair<std::string, std::string> iprange;
typedef std::set<iprange> iprange_set;
When I try to write lexical_cast around iprange and iprange_set with some other types such as Json::Value or std:string compiler is giving error since a typedef is just an alias not a real type, so it can't be overloaded.
is there a way to have a type that exhibit the properties of existing type without typedef ?
The result I am looking for is that I should be able to declare variables using that type and also use it as parameter in boost::lexical_cast
Posting code
#include <iostream>
#include <string>
#include <set>
#include <boost/lexical_cast.hpp>
using namespace std;
typedef set<string> ipaddr_list;
namespace boost {
template<>
string lexical_cast(const ipaddr_list* const & list)
{
return "qwe"; //actually code do convert ipaddr_list to string
}
};
int main()
{
ipaddr_list l;
l.insert("45.5.5.5-56.6.6.6");
string s = boost::lexical_cast<string>(l);
}
Compiler giving following error:
In file included from test.cpp:4:
/usr/include/boost/lexical_cast.hpp:349:13: error: implicit instantiation of undefined template
'boost::STATIC_ASSERTION_FAILURE'
BOOST_STATIC_ASSERT_MSG((result_t::value || boost::has_left_shift< std::basic_ostream< type >, T >::value),
^
and some more
You provided a specialization for lexical_cast(const ipaddr_list*) - a function taking a pointer. But you are not calling that specialization - you are not in fact passing a pointer to lexical_cast. Instead, you are calling a general-purpose implementation, which tries to send ipaddr_list instance to a stream, but naturally fails to find a suitable overload of operator<<. This is what the assert is telling you.

std::isgraph is ambiguous when `using namespace std` is used

I tried to use std::isgraph from <cctype> as a predicate in find_if. But compiler errored out saying:
error: no matching function for call to ‘find_if(__gnu_cxx::__normal_iterator< const char*, std::basic_string< char> >, __gnu_cxx::__normal_iterator< const char*, std::basic_string< char> >, < unresolved overloaded function type>)’
I have used using namespace std; and from my understanding there will be two isgraph functions visible in the global namespace. So ::isgraph or simply isgraph should be ambiguous and std::isgraph should not be ambiguous. On the contrary, using ::isgraph is OK while std::isgraph is not.
Can someone explain what I missed? A few related questions are What are the function requirements to use as the predicate in the find_if from the <algorithm> library? and C++ using standard algorithms with strings, count_if with isdigit, function cast. But they didn't answer why explicitly specifying std:: still doesn't resolve to the function in the std namespace.
EDIT:
#include <cctype>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
int main()
{
string root_line = "hello";
auto ind = distance(root_line.begin(), find_if(root_line.begin(), root_line.end(), std::isgraph));
cout << ind;
return 0;
}
I compiled the above code with g++ -std=c++11 of version 4.8.4
std::isgraph is overloaded.
To resolve the ambiguity you could cast it to the relevant function pointer type.
But in order to use it correctly the argument should be converted to unsigned char, so better define a wrapper function:
using Byte = unsigned char;
auto is_graphical( char const ch )
-> bool
{ return !!isgraph( Byte( ch ) ); }
Note that this only works with single-byte encodings, and that it depends on the current locale at the C level (see setlocale).
There is a std::isgraph defined in <cctype> and a different std::isgraph defiend in <locale>. Using overloaded functions as functors can be a pain as the compiler has difficulty figuring out which version of the function you want. You can resolve the ambiguity by casting, or using a lambda or named wrapper function as suggested by #Cheersandhth.-Alf
#include <cctype>
#include <algorithm>
#include <string>
#include <iostream>
int main()
{
std::string root_line = "hello";
auto ind = std::distance(root_line.begin(), std::find_if(root_line.begin(), root_line.end(), static_cast<int(*)(int)>(std::isgraph)));
std::cout << ind;
}
Live example: http://ideone.com/heSSEZ

unique_ptr has no member function

I am updating my gcc 4.4 to gCC 4.7, I will do this to use 4.7.
My problem is when I use unique_ptr. I wrote this code
#include <iostream>
#include <memory>
#include <CL/cl.h>
using namespace std;
/*
*
*/
int main(int argc, char** argv) {
std::unique_ptr<cl_platform_id[]>yt;
yt = std::unique_ptr<icl_platform_id[]> (new cl_platform_id [3]);
/* yt.get()[0] = ...... */ this is error no member found
return 0;
}
but I want to use yt member such as uique_ptr::get() and the only function that I get is operator*, so what is the problem?
Edited:
here is my problem:
http://image-load.biz/?di=6FBY
That would be a problem with your IDE's member suggestions. std::unique_ptr certainly does have a member pointer get() const noexcept;, in both the default template and the partial specialisation for arrays.
If you type get() yourself, then the compiler should be happy. Unfortunately, I've never used that IDE, so I can't help you fix its autocompleter.
Whether you should be calling get() is another question; you can access the array elements as yt[0] etc. get() is only for those rare occasions when you actually need a raw pointer.
You want something like:
std::unique_ptr<cl_platform_id[]> yt ( new cl_platform_id[3] );
yt[0].some_member();

Boost::Variant and function_types in it: How to put functions into Boost::variant?

Lyrics:
I try to implement a task pool over MPI. So I need some kind of RPC but one that would work between different parts of my program, meaning processor A wants processor B to call function C with argument D. We can not pass pointers to functions between processes like we do with threads, so we need some wrapper container to hold our function pointers at each process instance. All inside one source file\one program... So I started wondering about How to store functional objects with different signature in a container. My API Idea back then was wrong - it is better to define all functions in function pool at that pool construction (at least it shall be much easier to implement). But while implementing I faced next trouble:
Problem:
Such simple code (function_types, mpl::vector, variant):
#include <boost/function_types/function_type.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/variant.hpp>
#include <iostream>
#include <string>
template <class T>
int append(T val)
{
std::cout << "hello";
return 0;
}
int main()
{
boost::variant<boost::function_types::function_type< boost::mpl::vector<int,int> >::type , boost::function_types::function_type< boost::mpl::vector<int,std::string> >::type > a;
return 0;
}
Will not compile falling with:
Error 1 error C2066: cast to function type is illegal c:\program files\boost\include\boost\variant\variant.hpp 1231 1
And looking at source we see:
this code block:
variant()
{
// NOTE TO USER :
// Compile error from here indicates that the first bound
// type is not default-constructible, and so variant cannot
// support its own default-construction.
//
new( storage_.address() ) internal_T0();
indicate_which(0); // zero is the index of the first bounded type
}
So I wonder: How to get around this error?
Also I tried:
#include <boost/function_types/function_type.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/variant.hpp>
#include <boost/function.hpp>
#include <iostream>
#include <string>
template <class T>
int append(T val)
{
std::cout << "hello";
return 1;
}
int main()
{
boost::variant< boost::function<int (std::string) >, boost::function<int (int) > > a;
a= &append<int>;
return 0;
}
Which fails with:
Error 1 error C2668: 'boost::detail::variant::make_initializer_node::apply<BaseIndexPair,Iterator>::initializer_node::initialize' : ambiguous call to overloaded function c:\program files\boost\include\boost\variant\variant.hpp 1330
Any Ideas on how to make boost.variant hold functions?
Of course we can play with shared pointers to functors like so:
#include <boost/variant.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>
#include <string>
template <class in, class out>
struct s_append
{
out operator()(in val) {
std::cout << "hello";
return out();
}
};
int main()
{
boost::variant<boost::shared_ptr<s_append<int, int> >, boost::shared_ptr< s_append<std::string, int> > > a;
boost::shared_ptr<s_append<int, int> > b(new s_append<int, int> );
a=b;
return 0;
}
and it would compile but resulting API sucks - you have to 1) create functors for all functions you want to use (meaning limit there use of current process scope); 2) use shared_pointers and so I don't really even get how to call functions nested that way (simple first guess (*a)(22); just won't compile =( and API starts to be as bad as we would have using Boost.Any).
Try inserting a dummy type as the first argument of the variant. As the comment you found explains, only the first type in the variant is used for the variant's own default constructor. You could use an empty struct type for this (struct NoFunction {};).
That said, you may have been onto something with the idea to use boost::functions as the types in the variant...they are default-constructible at least. I'm not sure what the other error you had from that approach was caused by, but just wanted to let you know you could pursue that angle more if you can't use the dummy-type workaround I mentioned.

Error declaring hash_map in lex file

I'm working on writing a simple preprocessor for a compiler. Below is an edited snippet of my code:
%{
#include <string.h>
#include <hash_map>
#include "scanner.h"
#include "errors.h"
struct eqstr {
bool operator()(const char* s1, const char* s2) const {
return strcmp(s1, s2) == 0;
}
};
std::hash_map<const char*, char*, hash<const char*>, eqstr> defs; // LINE 28
%}
// Definitions here
%%
// Patterns and actions here
%%
When I compile I get the following error:
dpp.l:28: error: expected constructor,
destructor, or type conversion before
‘<’ token
Any ideas what might be wrong with this? I pretty much copied and pasted this line from the sgi documentation.
You need std::hash rather than just hash, since you have no using statement that will pull it into scope. Also, the default std::hash<const char *> will hash the pointer directly, which won't work for this use -- you need a hash function that hashes the c-string pointed at. You need to define your own specialization of hash, or your own hashing function -- the latter is probably better.