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.
Related
I can't understand why I have this error, apparently the isalpha function is redeclared twice (my editor marks me: "2 more overloads") but I don't understand why, this is my code:
#include <iostream>
#include <set>
#include <algorithm>
#include <ctype.h>
#include <string>
using namespace std;
int main(){
cin.tie(nullptr);ios_base::sync_with_stdio(false);
string line;
string::iterator prev, act;
while(cin>>line){
// act = find_if(line.begin(), line.end(), [](int x) {return isalpha(x);}); // GOOD
act = find_if(line.begin(), line.end(), isalpha); // ERROR
cout<<*act<<endl;
}
}
I use g++ (MinGW.org GCC-6.3.0-1) 6.3.0
Error:
1215.cpp: In function 'int main()':
1215.cpp:14:56: error: no matching function for call to 'find_if(std::__cxx11::basic_string<char>::iterator, std::__cxx11::basic_string<char>::iterator, <unresolved overloaded function type>)'
act = find_if(line.begin(), line.end(), isalpha); // ERROR
^
In file included from c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\algorithm:62:0,
from 1215.cpp:3:
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:3808:5: note: candidate: template<class _IIter, class _Predicate> _IIter std::find_if(_IIter, _IIter, _Predicate)
find_if(_InputIterator __first, _InputIterator __last,
^~~~~~~
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:3808:5: note: template argument deduction/substitution failed:
1215.cpp:14:56: note: couldn't deduce template parameter '_Predicate'
act = find_if(line.begin(), line.end(), isalpha); // ERROR
Note: if I don't use the "using namespace std" the code compiles and executes correctly.
Thanks in advance for any answers or advice
This is what might be happening.
There's an isalpha() in the <cctype> header under the std namespace and another isalpha() in the <locale> header under the very same std namespace. using namespace std pulls both into the your scope and thus the ambiguity while deducing the template.
Moral of the story: Avoid using using namespace std.
I can't understand why I have this error, apparently the isalpha function is redeclared twice (my editor marks me: "2 more overloads") but I don't understand why
Two overloads are declared, because the standard says that there are two overloads.
A good solution is to use a lambda, as you did in the comment. Unlike creating a function pointer, calling the function in the lambda allows the call to be resolved to the correct overload based on the passed arguments.
Your lambda should be improved though: Change the type of the parameter to unsigned char. This is needed because char may be a signed type, and if the value of a char is negative, then it will have a value outside the range of unsigned char, and passing a value outside the range of unsigned char into islpha will result in undefined behaviour. Fixed example:
auto isalpha = [](unsigned char c){
return std::isalpha(c);
};
act = find_if(line.begin(), line.end(), isalpha);
Also, remove the line using namespace std.
To complete # Zoso's answer:
Inside <iostream> are included <cctype> and locale_facets.h both define different std::isalpha functions .
Also, inside <cctype> includes <ctype.h> (which is in fact explicitly included in the example) and <ctype.h> defines an isalpha function (without the std namespace).
So one way to solve the problem is to call the isalpha function of<ctype.h>, for this it is necessary to exit the current namespace (std) with :: operator.
This code works:
#include <iostream>
#include <algorithm>
#include <ctype.h>
#include <string>
using namespace std;
int main(){
cin.tie(nullptr);ios_base::sync_with_stdio(false);
string line;
string::iterator prev, act;
while(cin>>line){
act = find_if(line.begin(), line.end(), ::isalpha);
cout<<*act<<endl;
}
}
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.
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.
I am working on flex (.lex file) in vmPlayer on linux, and I want to convert sass code to css code.
I want to work with a map of char arrays, to match variables in sass to their values. For some reason, I can not insert values to my map.
%{
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <map>
#include<iostream>
std::map<char[20], char[20]> dictionary; //MY DICTIONARY,GOOD
%}
%%
s dictionary.insert(std::pair<char[20], char[20]>("bb", "TTTT")); //PROBLEM
%%
it does not compile and gives me error:
hello.lex:30:84: error: no matching function for call to ‘std::pair<char
[20], char [20]>::pair(const char [3], const char [5])’
ine(toReturn); dictionary.insert(std::pair<char[20], char[20]>("bb",
"TTTT"));
In general, I am not sure what C libraries I can use easily on flex and which are more fishy using flex.
Is there a syntax problem?
The issue in the generated C++ code is that pair(const char [3], const char [5]) (which is the size of your constant strings) has nothing to do with pair(const char [20], const char [20]). It is just not the same type.
3 solutions:
add template arguments for char array sizes (EDIT: does not work, because it would still have to be the same sizes for all elements)
use char [] instead if you only have constants to insert
or better & simpler & covers all cases: use std::string type, which accepts char arrays in its constructor.
like this:
%{
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <map>
#include<iostream>
std::map<std::string, std::string> dictionary; //MY DICTIONARY,GOOD
%}
%%
s dictionary.insert(std::pair<std::string, std::string>("bb", "TTTT"));
%%
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