I tried using the std::replace algorithm:
replace(out.begin(), out.end(), '\r', '\r\n'); // error
replace(out.begin(), out.end(), "\r", "\r\n"); // error
replace(out.begin(), out.end(), "\\r", "\\r\\n"); // error
I always get errors that the parameters are ambigous. How exactly can I specify the \r and \n so the compiler will not complain ?
edit:
errors:
could not deduce template argument for 'const _Ty &' from 'const char [5]'
template parameter '_Ty' is ambiguous
'replace': no matching overloaded function found
While in principle this might be solved with some combination of standard/Boost functions, it's specific enough to get its own function, and thus its own impl as well. Which could be as simple as this:
std::string cr_to_crlf(std::string const& s) {
std::string result;
result.reserve(s.size());
for (char c : s) {
result += c;
if (c == '\r') {
result += '\n';
}
}
return result;
}
Related
So I am having an issue using basename for one of my programming assignments for school
I have tried getting a simplier version of it working -- I got it working however, still confused exactly what I am supposed to do in this case
// $Id: util.cpp,v 1.1 2016-06-14 18:19:17-07 - - $
#include <libgen.h>
#include <cstring>
using namespace std;
#include "util.h"
ydc_exn::ydc_exn (const string& what): runtime_error (what) {
}
string exec::execname_; // Must be initialized from main().
int exec::status_ = EXIT_SUCCESS;
void exec::execname (const string& argv0) {
execname_ = basename (argv0.c_str());
cout << boolalpha;
cerr << boolalpha;
DEBUGF ('Y', "execname = " << execname_);
}
void exec::status (int new_status) {
new_status &= 0xFF;
if (status_ < new_status) status_ = new_status;
}
ostream& note() {
return cerr << exec::execname() << ": ";
}
ostream& error() {
exec::status (EXIT_FAILURE);
return note();
}
Just trying to get the code to compile --- my error message in c++ is:
'
util.cpp:15:16: error: no matching function for call to 'basename'
execname_ = basename (argv0.c_str());
^~~~~~~~
/usr/include/libgen.h:40:7: note: candidate function not viable: 1st argument ('const std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>
>::value_type *' (aka 'const char *')) would lose const qualifier
char *basename(char *);
^
1 error generated.
make: *** [util.o] Error 1'
basename takes char* as argument, which is not const, meaning the function is allowed to modify the value.
const string& argv0 is const, meaning the value of argv0 must not be modified.
Thus you are not allowed to call basename with argv0.c_str() as parameter, as that would violate the const qualifier.
The error message is clear: 1st argument ... would lose const qualifier.
So either change argv0 to not be const (probably not a good idea), or change basename to take a const char* parameter (probably the better idea), or change basename to work with std::string instead of char* like the rest of your code (probably the best idea).
So apparently basename is a unix function that you cannot change. (Thanks Nevin!) From the manpage:
Both dirname() and basename() may modify the contents of path, so it may be desirable to pass a copy when calling one of these functions.
In that case I recommend creating a copy of argv0. The simplest way of doing this would be to change the signature of execname to this:
void exec::execname(std::string argv0)
I think that your central problem is including libgen.h as well as cstring. If you look at the prototypes for basename in those files, they're different. If you're building this on linux, you'll see a comment in the libgen.h version which should be enlightening.
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/basename.html and
https://linux.die.net/man/3/basename are useful here too.
I suggest removing the #include <libgen.h> and trying again.
I am playing with some piece of code, taken from Avoid if-else branching in string to type dispatching answer from Vittorio Romeo, but rewritten to use with C++14 cause Vittorios version uses C++17 fold expressions. I also thought the rewrite would be a good exercise.
Here is the code:
#include <type_traits>
#include <iostream>
#include <utility>
#include <string>
template<char... Cs>
using ct_str = std::integer_sequence<char, Cs...>;
template<typename T, T... Cs>
constexpr ct_str<Cs...> operator""_cs() { return {}; }
template<typename Name, typename T>
struct named_type
{
using name = Name;
using type = T;
};
template<typename... Ts>
struct named_type_list { };
using my_types = named_type_list<
named_type<decltype("int"_cs), int>,
named_type<decltype("bool"_cs), bool>,
named_type<decltype("long"_cs), long>,
named_type<decltype("float"_cs), float>,
named_type<decltype("double"_cs), double>,
named_type<decltype("string"_cs), std::string>
>;
template<std::size_t... Is, char... Cs>
constexpr bool same_impl(const std::string& s,
std::integer_sequence<char, Cs...>,
std::index_sequence<Is...>)
{
const char c_arr[] = {Cs...};
for (std::size_t i = 0; i != sizeof...(Cs); ++i) {
if (s[i] != c_arr[i]) return false;
}
return true;
//Original C++17 (fold expression)
//return ((s[Is] == Cs) && ...);
}
template<char... Cs>
constexpr bool same(const std::string& s, std::integer_sequence<char, Cs...> seq)
{
std::cout << "checking '" << s << "' against '";
std::initializer_list<bool>{ bool(std::cout << Cs)... };
std::cout << "'\n";
return s.size() >= sizeof...(Cs)
&& same_impl(s, seq, std::make_index_sequence<sizeof...(Cs)>{});
}
template<typename... Ts, typename F>
void handle(named_type_list<Ts...>, const std::string& input, F&& f)
{
using expand_type = int[];
expand_type{ 0, (same(input, typename Ts::name{}) && (f(Ts{}), false), 0)... };
//(void)std::initializer_list<int> {
// ( (same(input, typename Ts::name{}) && (f(Ts{}), false) ), 0)...
//};
//Original C++17 (fold expression)
//( (same(input, typename Ts::name{}) && (f(Ts{}), true) ) || ...);
}
int main(int argc, char** argv)
{
const std::string input{"float"};
handle(my_types{}, input, [](auto t)
{
std::cout << typeid(typename decltype(t)::type).name() << "\n";
// TEST: define std::vector with value_type (matched type "float") and add a few values
using mtype = typename decltype(t)::type;
std::vector<mtype> x;
x.push_back(2.2); // <-- does not compile
});
return 0;
}
I assume problem lies in the handle function that seems not to stop the evaluation properly. It should stop at the first invocation of f() in case of a match. Instead, it executes f() in case of a match as expected, but continues executing the remaining types in the named_type_list.
The current code results in this output:
checking 'float' against 'int'
checking 'float' against 'bool'
checking 'float' against 'long'
checking 'float' against 'float'
f
checking 'float' against 'double'
checking 'float' against 'string'
Actually I have no clue how to get that fixed. I tried to rewrite the C++17 fold expression using the std::initializer_list trick and also tried to use an expander (the uncommented part in the handle body. So I guess it is the expression itself not working properly.
Unfortunately I am out of ideas whats really happening at this point, also the fact that I am not experienced with Meta-Programming/Compile-time evaluation.
Another problem arises with an possible use of this code:
My use case would be in an XML property reader where I have type/value tags, e.g. <attribute type="double" value="2.5"/>, applying something like the handle function to get the typename from the type attribute value. That type I could use to further process the value.
For this I added within the handle f()-body in main() 3 lines, defining an std::vector with the found type and trying to add a value to it. This code does not compile, g++ responds with
error: no matching function for call to ‘std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > >::push_back(double)’
I guess this is the mixup out of compile-time and run-time behaviour and it does not work this way and that makes me curious how I could further process/use the matched type.
Thanks for your time on explanation, any help is greatly appreciated!
||, of course, short-circuits. Your version doesn't. I don't see short-circuiting as essential to correctness here, but if you want, it's easily implemented with an additional bool:
bool found = false;
expand_type{ 0, (!found &&
same(input, typename Ts::name{}) &&
(f(Ts{}), found = true), 0)... };
The second problem is because your handler function must be validly callable for every possible type in the type list, but you can't push_back 2.2 into a std::vector<std::string>. As an example, you might have something that obtains the value as a string, and the handler body could lexical_cast it to mtype.
I try to return simple array with boost::optional
boost::optional<const char *> foo () {
char ar[100] = {};
return boost::make_optional(true, ar);
}
and I got the following error:
could not convert ‘boost::make_optional(bool, const T&) [with T = char [100]](ar)’ from ‘boost::optional<char [100]>’ to ‘boost::optional<const char*>’ return boost::make_optional(true, ar);
How can I handle such confusion?
Closest you can do is by using a wrapper with value semantics.
That wrapper is std::array:
boost::optional<std::array<char, 100> > foo () {
std::array<char, 100> ar {};
return boost::make_optional(true, ar);
}
About arrays vs. pointers:
How do I use arrays in C++?
boost::make_optional deduced ar as char [100] type, but it expected const char *. By default implicit casting is not happened in template parameter deduction.
If you want to use raw pointer, it is possible to use the following solution:
boost::optional<const char *> foo () {
char ar[100] = {};
return boost::make_optional(true, static_cast<const char *>(ar));
}
But in this case you lose information how many elements located in this array and maybe better to use in foo() function std::vector or std::array as in example of sehe
Good luck !!
I have a string-
std::string out;
and an iterator over that string-
std::string::iterator pos = out.begin();
if I do -
if(!out.empty() || pos > out.begin())
out.erase(pos--);
It segfaults, with this error-
Program received signal SIGSEGV, Segmentation fault.
__memmove_ssse3 () at ../sysdeps/x86_64/multiarch/memcpy-ssse3.S:2821
2821 ../sysdeps/x86_64/multiarch/memcpy-ssse3.S: No such file or directory.
What am I missing?
For some context, I'm implementing line editing with ncurses and this code defines behaviour when backspace is pressed.
EDIT
It segfaults even after I move the decrement out of the call.
here is an MCVE -
#include <string>
#include <ncurses.h>
int main()
{
initscr();
cbreak();
keypad(stdscr, true); //Seems to be causing the error
std::string out;
std::string::iterator pos = out.begin();
short ch;
bool insert = false;
int y, x;
while(true)
{
ch = getch(); //Get next character
if(ch == '\n')
break; //End of line
else if(ch == KEY_BACKSPACE) //Backspace behaviour defined here
{
if(!out.empty())
{
out.erase(pos); //Character erased from string as per backspace
addch('\b'); //Erasure reflected on screen
std::string temp(pos, out.end()); //
getyx(stdscr, y, x);
mvaddstr(y, x - 1, temp.c_str());
}
}
else if(std::isalnum(ch) || std::ispunct(ch)) //Normal characters
{
if(!insert) //If insert is off
out.insert(pos++, ch); //Character inserted normally
else //Insert is on
{
*pos = ch; //Overwrite characters
pos++;
}
}
}
endwin();
return 0;
}
Compile with
g++ -lncurses -std=c++11
-Wall gives no clues.
This is expected behaviour for std::string. In the C++ standard, validity of string iterators is not garanteed after a modification of the string, contrary to other types with stronger requirements.
In [string.require] (§21.4.1), the standard states:
References, pointers, and iterators referring to the elements of a
basic_string sequence may be invalidated by the following uses of
that basic_string object: [...] Calling non-const member functions,
except operator[], at, data, front, back, begin, rbegin, end, and
rend.
I have the following use of std::reference_wrapper for a build in type (double) and for a user defined type (std::string).
Why do they behave differently in the case of the stream operator?
#include<functional> //reference wrapper
#include<iostream>
void fd(double& d){}
void fs(std::string& s){}
int main(){
double D = 5.;
std::reference_wrapper<double> DR(D);
std::cout << "DR = " << DR << std::endl; //ok
fd(DR); // ok
std::string S = "hello";
std::reference_wrapper<std::string> SR(S);
std::cout << "SR = " << static_cast<std::string&>(SR) << std::endl; // ok
std::cout << "SR = " << SR << std::endl; // error: invalid operands to binary expression ('basic_ostream<char, std::char_traits<char> >' and 'std::reference_wrapper<std::string>')
fs(SR); // ok
}
http://coliru.stacked-crooked.com/a/fc4c614d6b7da690
Why in the first case DR is converted to double and printed and in the second it is not? Is there a work around?
Ok, I see now, in the ostream case I was trying to called a templated function that is not resolved:
#include<functional> //reference wrapper
void double_fun(double const& t){};
template<class C>
void string_fun(std::basic_string<C> const& t){};
int main(){
double D = 5.;
std::reference_wrapper<double> DR(D);
double_fun(DR); //ok
std::string S = "hello";
std::reference_wrapper<std::string> SR(S);
string_fun(SR); // error: no matching function for call to 'string_fun'
string_fun(SR.get()); // ok
string_fun(static_cast<std::string&>(SR)); // ok
string_fun(*&SR); // would be ok if `std::reference_wrapper` was designed/coded differently, see http://stackoverflow.com/a/34144470/225186
}
For the first part TC gave you the answer. That is, operator<< for basic_string is templated, and template argument deduction doesn't look through implicit conversions.
You could alternatively call SR.get() if you don't want to explicitly to static_cast your reference wrapper.
Now for the second part, string_fun takes as input arguments std::basic_string<C> objects. When you call:
string_fun(SR);
with SR as input parameter which is of type std::reference_wrapper<std::string>, naturally you get a type mismatch.
What you can do is provide an additional overload:
template<class C>
void string_fun(std::reference_wrapper<std::basic_string<C>> const& t) {
};
Live Demo
Or if you want a more unified treatment you could define your string_fun to take template template arguments, and resolve the type with some kind of type trait magic like bellow:
template<template<typename...> class C, typename T>
void
string_fun(C<T> const &t) {
std::cout <<
static_cast<std::conditional_t<
std::is_same<
std::reference_wrapper<T>, C<T>>::value, T, std::basic_string<T>>>(t) << std::endl;
}
Live Demo