I'm getting compile error in this line:
cout << (MenuItems[i].Checkbox ? (MenuItems[i].Value ? txt::mn_yes : txt::mn_no) : MenuItems[i].Value)
Error:
menu.cpp|68|error: invalid conversion from 'int' to 'const char*'
menu.cpp|68|error: initializing argument 1 of 'std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]'
MenuItems is std::vector of following class:
class CMenuItem
{
public:
string Name;
int Value;
int MinValue, MaxValue;
bool Checkbox;
CMenuItem (string, int, int, int);
CMenuItem (string, bool);
};
mn_yes and mn_no are std::strings.
Compiler is MinGW (version that is distributed with code::blocks).
The two possible conditional values have to be convertible to a common type. The problem is that the left of the outer conditional:
(MenuItems[i].Value ? txt::mn_yes : txt::mn_no)
is always a string, but the right:
MenuItems[i].Value
is an int. It tries to find a way by going const char *->string, but then it won't allow the int to const char * conversion (which is good, because it would be meaningless). Just do:
if(MenuItems[i].Checkbox)
{
cout << (MenuItems[i].Value ? txt::mn_yes : txt::mn_no);
}
else
{
cout << MenuItems[i].Value;
}
or similar.
Related
I have the following code:
#include <string>
#include <iostream>
void f(const std::string& s = "")
{
std::cout << "\"" << s << "\"" << std::endl;
}
int main()
{
std::string s1 = "qwe";
f();
f("asd");
f(s1);
}
How bad (if at all) are the calls with the temporary and without the parameters?
As far as I know this compiles only due to the fact that const reference prolongs the life of the temporary until the end of a method http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/
Trying to compile the same example without the const next to s parameter fails.
#include <string>
#include <iostream>
void f(std::string& s = "")
{
std::cout << "\"" << s << "\"" << std::endl;
}
int main()
{
std::string s1 = "qwe";
f();
f("asd");
f(s1);
}
Compilation
g++-5 -O3 -Wall --std=c++11 main.cpp && ./a.out
main.cpp:4:27: error: invalid initialization of non-const reference of type ‘std::string& {aka std::basic_string<char>&}’ from an rvalue of type ‘std::string {aka std::basic_string<char>}’
void f(std::string& s = "")
^
In file included from /usr/include/c++/5/string:52:0,
from main.cpp:1:
/usr/include/c++/5/bits/basic_string.h:2893:7: note: after user-defined conversion: std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());
^
main.cpp: In function ‘int main()’:
main.cpp:12:5: error: invalid initialization of non-const reference of type ‘std::string& {aka std::basic_string<char>&}’ from an rvalue of type ‘std::string {aka std::basic_string<char>}’
f();
^
In file included from /usr/include/c++/5/string:52:0,
from main.cpp:1:
/usr/include/c++/5/bits/basic_string.h:2893:7: note: after user-defined conversion: std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());
^
main.cpp:4:6: note: in passing argument 1 of ‘void f(std::string&)’
void f(std::string& s = "")
^
main.cpp:13:10: error: invalid initialization of non-const reference of type ‘std::string& {aka std::basic_string<char>&}’ from an rvalue of type ‘std::string {aka std::basic_string<char>}’
f("asd");
^
In file included from /usr/include/c++/5/string:52:0,
from main.cpp:1:
/usr/include/c++/5/bits/basic_string.h:2893:7: note: after user-defined conversion: std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());
^
main.cpp:4:6: note: initializing argument 1 of ‘void f(std::string&)’
void f(std::string& s = "")
It's not a horrible practice, but it's generally better to provide overloads:
void f(std::string const& s) { std::cout << "\\" << s << "\\\n"; }
void f() { f(""); }
It avoids some language features that end up being confusing to many people. For example, what does this print?
struct base { virtual void f(int i = 42) { std::cout << i; } };
struct derived : base { void f(int i = 19) { std::cout << i; }};
int main() { base * b = new derived(); b->f(); }
There are also ambiguity errors that can come up when you're using default parameters that don't when you use overloads.
As far as const references in particular, that doesn't really matter much. The default value binds to reference for the lifetime of the function call. It has no effect at all really. You might get better results using values sometimes when the compiler can perform certain optimizations that are not possible with reference parameters, but generally it's not something to be concerned with.
Of course, this doesn't work with non-const references because they don't bind to temporaries.
The default value is for allowing you to call function without any arguments, so use reference parameter with default value if you sometimes will not pass argument to function, otherwise there is no matter to do so.
I have the following code and get the error later described how do i correct this?
The objective behind is to parse the following sentence into variables :
temp1+temp2=10
Code:
int main()
{
string line,var1;
int limit,len;
//some code here
// parse function declarartion :string parse(string ,char ,int &)
f1>>line;
len=line.length();
var1=parse(line,'+',limit);
line.copy(line,len-limit,limit);
//some code here
}
Error:
alice.cpp: In function ‘int main()’:
alice.cpp:65:40: error: no matching function for call to ‘std::basic_string<char>::copy(std::string&, int, int&)’
alicebob.cpp:65:40: note: candidate is:
/usr/include/c++/4.6/bits/basic_string.tcc:724:5: note: std::basic_string<_CharT, _Traits, _Alloc>::size_type std::basic_string<_CharT, _Traits, _Alloc>::copy(_CharT*, std::basic_string<_CharT, _Traits, _Alloc>::size_type, std::basic_string<_CharT, _Traits, _Alloc>::size_type) const [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>, std::basic_string<_CharT, _Traits, _Alloc>::size_type = unsigned int]
/usr/include/c++/4.6/bits/basic_string.tcc:724:5: note: no known conversion for argument 1 from ‘std::string {aka std::basic_string<char>}’ to ‘char*’
If you just want to copy a substring into another string, why don't you use substr() instead?
int main()
{
std::string line("ceva5");
std::string var1;
int limit = 1,len;
//some code here
// parse function declarartion :string parse(string ,char ,int &)
// f1>>line;
len=line.length();
//
// var1=parse(line,'+',limit);
line = line.substr(limit, len-limit);
//some code here
std::cout << line << std::endl;
}
This should do what you want.
EDIT: I have not implemented your function but changed the code to work as string's copy().
Here is the explain: http://www.cplusplus.com/reference/string/string/copy/ ,The first arg is char*, So,Accroding to your question,I think your code should be
line.copy((char *)line.c_str(),len-limit,limit); // wrong code, lost the const
but this code is dangerous,Because std::copy()'s first arg is an array of characters to store the string 's substring, So,I think you code has something wrong.
Here is simple code:
std::string test1 = "test1";
char buffer[10] = {0};
test1.copy(buffer,2,3);
std::cout << "buffer is: " << buffer << std::endl;
and the output is :"buffer is: t1".
I have a map of pointer to member declared as :
std::map<char, T (Operand::*)(const T &, const T &)> op_map;
I fill my map with pointer to member directly in the constructor of my class with :
op_map['+'] = &Operand::op_add;
For example, op_add source code is :
T op_add(const T & a, const T & b) {
return a + b;
}
And I want to call my pointer to member from a const function. Here is the source code :
IOperand *res_int32(char op, const IOperand & rhs) const {
IOperand *res = const_cast<IOperand *>(&rhs);
Operand<int> *tmp = dynamic_cast<Operand<int>*>(res);
T res_calc = (this->*op_map[op])(_value, (T)tmp->getValue());
}
But it makes me always an error :
Operand.hpp:70:64: error: passing ‘const std::map<char, double (Operand<double>::*)(const double&, const double&), std::less<char>, std::allocator<std::pair<const char, double (Operand<double>::*)(const double&, const double&)> > >’ as ‘this’ argument of ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = char, _Tp = double (Operand<double>::*)(const double&, const double&), _Compare = std::less<char>, _Alloc = std::allocator<std::pair<const char, double (Operand<double>::*)(const double&, const double&)> >, std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = double (Operand<double>::*)(const double&, const double&), std::map<_Key, _Tp, _Compare, _Alloc>::key_type = char]’ discards qualifiers [-fpermissive]
Operand.hpp:70:64: error: invalid conversion from ‘const Operand<double>* const’ to ‘Operand<double>*’ [-fpermissive]
Have you got any solution ?
Thank you.
operator[] can't be applied to a const map, since it inserts a new element if the key is not found.
In C++11, there is an at function which throws an exception if the key is not found:
T res_calc = (this->*op_map.at(op))(_value, (T)tmp->getValue());
^^^^^^^
In C++03, you'll need to use find:
map_type::const_iterator found = op_map.find(op);
if (found != op_map.end()) {
T res_calc = (this->*(found->second))(_value, (T)tmp->getValue());
} else {
// handle error
}
You'll also need to change the type of the member functions in the map to
T (Operand::*)(const T &, const T &) const
^^^^^
in order to call them on this from a const member function.
Just make op_add a const member function.
T op_add(const T & a, const T & b) const // <<<
{
return a + b;
}
And instead of the std::map::operator[] use std::map::find http://www.cplusplus.com/reference/stl/map/find/
EDIT:
You also need to change the map type to std::map<char, T (Operand::*)(const T &, const T &) const> op_map, as correctly pointed by R. Martinho Fernandes.
If you know what you are doing, you can try to compile with the c++ flag -fpermissive as G++ said.
I have a program that generates a single random character, using the randomCharacter function, and random strings, using the randomString function. The latter utilises the former, and breedWithMutation uses randomCharacter to probabilistically mutate a representation of a gene sequence.
#include <ctime>
#include <boost/random.hpp>
typedef boost::mt19937 randAlgorithm;
int mutationsPerGeneration = 100;
double probabilityOfMutation = 0.05;
string potentialAlleles = "abcdefghijklmnopqrstuvwxyz ";
size_t numberOfAlleles = potentialAlleles.size();
double random01(randAlgorithm & engine)
{
boost::uniform_real<double> u01;
return u01(engine);
}
int randomInteger(randAlgorithm & engine, size_t min, size_t max) {
boost::uniform_int<> minmax(min, max);
return minmax(engine);
}
string randomCharacter(randAlgorithm & engine, string charSet, size_t charSetSize) {
return charSet[randomInteger(engine, 0, charSetSize)];
}
string randomString(randAlgorithm & engine, size_t length, string charSet, size_t charSetSize) {
string s;
s.reserve(length);
for (int i = 0; i < length; i++) {
s.append(randomCharacter(engine, charSet, charSetSize));
}
return s;
}
string breedWithMutation(randAlgorithm & engine, string originalGenome, size_t genomeSize) {
string mutatedGenome;
mutatedGenome.reserve(genomeSize);
double mutationDraw;
for (size_t i = 0; i < genomeSize; i++) {
mutationDraw = random01(engine);
if (mutationDraw < probabilityOfMutation) { //The allele undergoes mutation
mutatedGenome.append(randomCharacter(engine, potentialAlleles, numberOfAlleles));
}
else {
mutatedGenome.append(originalGenome[i]);
}
}
return mutatedGenome;
}
However, when I build the application, I get these errors:
main.cpp: In function ‘std::string randomCharacter(randAlgorithm&, std::string, size_t)’:
main.cpp:31:55: error: invalid conversion from ‘char’ to ‘const char*’
main.cpp:31:55: error: initializing argument 1 of ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]’
main.cpp: In function ‘std::string breedWithMutation(randAlgorithm&, std::string, size_t)’:
main.cpp:53:45: error: invalid conversion from ‘char’ to ‘const char*’
main.cpp:53:45: error: initializing argument 1 of ‘std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::append(const _CharT*) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>, std::basic_string<_CharT, _Traits, _Alloc> = std::basic_string<char>]’
The line numbers in the errors don't line up perfectly, I realise, but the first two errors refer to the only line in randomCharacter, and the third and fourth errors refer to this line: mutatedGenome.append(originalGenome[i]); in breedWithMutation. What is causing this error?
In C++, char and string are distinctly different types. One cannot implicitly convert a char value to a string (as you are trying to do in randomCharacter).
You could change the return type of randomCharacter to be char instead of string, though that may require changes elsewhere too (I haven't reviewed your code in detail).
Change the return type of randomCharacter() to char.
It's not an invalid conversion to const char, it's an invalid conversion to const char*. Strings in plain C are just arrays of characters, or const char*s. So, you're using a single character where you should be using a string.
To examine one instance: You've set up randomCharacter() to return a C++ string, but in actuality, you're trying to return a single character from charSet. It makes more sense to me for you to make the function return a char, but that's your decision to make.
I'm going over the boost-proto tutorial, and ran into this problem with the lazy pow function example. This is the example code:
// Define a pow_fun function object
template<int Exp> // , typename Func>
struct pow_fun
{
typedef double result_type;
double operator()(double d) const
{
return pow(d, Exp);
}
};
// Define a lazy pow() function for the calculator DSEL.
// Can be used as: pow< 2 >(_1)
template<int Exp, typename Arg>
typename proto::result_of::make_expr<
proto::tag::function // Tag type
, pow_fun<Exp> // First child (by value)
, Arg const & // Second child (by reference)
>::type const
mypow(Arg const &arg)
{
return proto::make_expr<proto::tag::function>(
pow_fun<Exp>() // First child (by value)
, boost::ref(arg) // Second child (by reference)
);
}
Now, if I try to
proto::display_expr( mypow<2>(_1) );
the compiler complains that it doesn't have operator<< for the
function expression. How do I define one?
Thanks.
The compiler error is:
/usr/include/boost/proto/debug.hpp:146: error: no match for ‘operator<<’ in ‘std::operator<< [with _Traits = std::char_traits](((std::basic_ostream >&)((std::basic_ostream >*)std::operator<< [with _Traits = std::char_traits](((std::basic_ostream >&)((std::basic_ostream >*)std::operator<< [with _Traits = std::char_traits](((std::basic_ostream >&)((std::basic_ostream >*)std::operator<< [with _CharT = char, _Traits = std::char_traits](((std::basic_ostream >&)((std::ostream*)((const boost::proto::functional::display_expr*)this)->boost::proto::functional::display_expr::sout_)), std::setw(((const boost::proto::functional::display_expr*)this)->boost::proto::functional::display_expr::depth_)))), (((const boost::proto::functional::display_expr*)this)->boost::proto::functional::display_expr::first_ ? ((const char*)"") : ((const char*)", "))))), boost::proto::tag::proto_tag_name((boost::proto::tag::terminal(), boost::proto::tag::terminal()))))), ((const char*)"(")) << boost::proto::value [with Expr = boost::proto::exprns_::expr >, 0l>](((const boost::proto::exprns_::expr >, 0l>&)((const boost::proto::exprns_::expr >, 0l>*)expr)))’
Which proto version is this ? The latest don't require the << overload anymore and default to typeid to display name if needed. Could you post the actual error message ?