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.
Related
I have a problem with .append methon in C++.
This is my code:
#include<iostream>
#include<string>
using namespace std;
int main(){
char caratteri[] = {"ciao amici"};
string str = "ciao amici";
string token = "";
for(int i = 0; i<str.length(); i++)
{
if(str[i+1] == ' '){
token = "";
}
char current_token = str[i];
token.append(string(current_token));
i++;
}
}
And this is a part of my output:
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\basic_string.h:397:7: note: no known conversion for argument 1 from 'char' to 'const std::__cxx11::basic_string<char>&'
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\basic_string.h:389:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
basic_string(const _Alloc& __a) _GLIBCXX_NOEXCEPT
^~~~~~~~~~~~
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\basic_string.h:389:7: note: no known conversion for argument 1 from 'char' to 'const std::allocator<char>&'
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\basic_string.h:380:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string() [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
basic_string()
^~~~~~~~~~~~
Why have I got this problem? Can I solve it?
Thank you very much :)
You try to create a std::string from a char here:
token.append(
string(current_token) // <- this part
);
To create a std::string from a single char, you need to supply how many times you want the char repeated:
token.append(string(1, current_token));
Fortunately, append has en overload that lets you do that directly, without creating an intermediate std::string:
token.append(1, current_token);
But the easiest would probably be to use the operator+= overload to add a single char:
token += current_token;
Note also that this
if(str[i+1] == ' ')
will access str[str.length()] when i == str.length() - 1. That is accessing it out of bounds. It will probably work anyway because there's a \0 stored just out of bounds, but I recommend that you fix that logic.
Summary
I have a class to which I've added a typecast operator to convert to std::u16string. The signature of this operator looks as follows:
operator const std::u16string() const;
In my .cpp file, I try converting an object of my class's type to std::u16string as follows:
std::u16string sUTF16Password = static_cast<std::u16string>(Password_);
On Visual Studio 2017, this works just fine. However, GCC 6.3 on my Raspberry Pi gives the following error at compile time:
error : call of overloaded 'basic_string(MyClass&)' is ambiguous
What is the right way to write this typecast? Searching on Google brings a lot of hits for character encoding conversions, but that's not my problem here. I don't understand why the basic_string constructor is being called here despite using static_cast.
Full example
Here's a minimal example. Compiling it with g++ main.cpp fails on my Raspberry Pi.
#include <iostream>
#include <string>
class MyClass
{
private:
std::u16string Str;
public:
MyClass() { Str = u"abcd"; }
operator const char16_t*() const { return Str.c_str(); }
operator std::u16string() const { return Str; }
};
int main()
{
MyClass Tester;
std::u16string TestStr = static_cast<std::u16string>(Tester);
for (size_t idx = 0; idx < TestStr.size(); idx++)
std::cout << idx << ": " << TestStr[idx] << std::endl;
return 0;
}
The output of gcc --version is gcc (Raspbian 6.3.0-18+rpi1+deb9u1) 6.3.0 20170516.
The full output from g++ main.cpp is:
main.cpp: In function ‘int main()’:
main.cpp:17:61: error: call of overloaded ‘basic_string(MyClass&)’ is ambiguous
std::u16string TestStr = static_cast<std::u16string>(Tester);
^
In file included from /usr/include/c++/6/string:52:0,
from /usr/include/c++/6/bits/locale_classes.h:40,
from /usr/include/c++/6/bits/ios_base.h:41,
from /usr/include/c++/6/ios:42,
from /usr/include/c++/6/ostream:38,
from /usr/include/c++/6/iostream:39,
from main.cpp:1:
/usr/include/c++/6/bits/basic_string.h:476:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::__cxx11::basic_string<_
CharT, _Traits, _Alloc>&&) [with _CharT = char16_t; _Traits = std::char_traits<char16_t>; _Alloc = std::allocator<char16_t>]
basic_string(basic_string&& __str) noexcept
^~~~~~~~~~~~
/usr/include/c++/6/bits/basic_string.h:454:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&
) [with _CharT = char16_t; _Traits = std::char_traits<char16_t>; _Alloc = std::allocator<char16_t>]
basic_string(const _CharT* __s, const _Alloc& __a = _Alloc())
^~~~~~~~~~~~
/usr/include/c++/6/bits/basic_string.h:397:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_st
ring<_CharT, _Traits, _Alloc>&) [with _CharT = char16_t; _Traits = std::char_traits<char16_t>; _Alloc = std::allocator<char16_t>]
basic_string(const basic_string& __str)
^~~~~~~~~~~~
If I remove the typecast to const char16_t* this example compiles just fine. I still don't understand why having both typecasts is a problem.
If you compile as C++14 (or earlier), you'll get this ambiguous call, because std::u16string(char16_t*) participates in the overload resolution (via MyClass::operator const char16_t*()) as well as MyClass::operator std::u16string() that would appear to be a better match.
This can be overcome in several ways:
Compile as C++17 (or later) with GCC 7 or later (sadly, this doesn't help with GCC 6).
Remove operator const char16_t*().
Add explicit to operator const char16_t*() (or to both conversion operators).
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'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.