How do I use overloaded functions with default arguments in algorithms? - c++

I know the answer to the frequently-asked How do I specify a pointer to an overloaded function?: Either with assignment or with a cast, and every other C++ tutorial uppercases a string like this (give or take static_cast):
transform(in.begin(), in.end(), back_inserter(out), (int(*)(int)) std::toupper);
Or like this:
int (*fp)(int) = std::toupper;
transform(in.begin(), in.end(), back_inserter(out), fp);
Which neatly selects the <cctype> overload of std::toupper.
But this begs the question: How can I select the <locale> overload in a similar manner?
char (*fp2)(char, const std::locale&) = std::toupper;
transform(in.begin(), in.end(), back_inserter(out), fp2);
// error: too few arguments to function
Or, more practically, consider someone trying to use the C++11 std::stoi in an algorithm to convert a vector of strings to a vector of integers: stoi has two overloads (string/wstring), each taking two additional default arguments.
Assuming I don't want to explicitly bind all those defaults, I believe it is impossible to do this without wrapping such call in an auxiliary function or lambda. Is there a boost wrapper or TMP magic to do it for me in completely generic manner? Can a wrapper like call_as<char(char)>(fp2) or, more likely, call_as<int(const std::string&)>(std::stoi) even be written?

It's funny, I was doing something similar. The best way I found to do it was using lambdas as follows, because otherwise, you have to use a typedef to get the right overload and a std::bind to get rid of the locale, or not use the locale. However, this works much more cleanly:
static const std::locale loc;
transform(in.begin(), in.end(), back_inserter(out), [&loc](char c) {
return std::toupper(c, loc);
});
I use the static to save the effort of reallocating each time.
Or you could get a typedef and do:
std::bind((LocaleCompare)std::toupper, std::placeholders::_1, loc); // UGLY!

You could should create a typedef of that functon pointer type, and then cast the function.
typedef char (*LocaleToUpper)(char, const std::locale&) ;
char (*fp2)(char, const std::locale&) = (LocaleToUpper)toupper;

Related

fmt Library - Formatting to a (compile-time) string_view

I would like to use the fmt library to create a string_view from my format args. There is plenty documented about passing in a compile-time string as the format string, however, I want to output a compile-time string, so that I may use it in other static parts of my code. Is there a way to do this? So far, all the functions I have seen return a std::string; I also tried format_to, but it seems to be explicitly disabled for a string_view iterator (which I am assuming wouldn't work compile-time anyway, as it's mutating). It may be simple and I'm just looking in the wrong places, I don't know.
I would like to be able to do something akin to the following:
consteval std::string_view example(unsigned i){
return fmt::something<std::string_view>("You sent {}"sv, i);
}
So far, this library seems to provide what I need, but, it would be advantageous to avoid a second dependency.
You can do this with format string compilation (FMT_COMPILE):
#include <fmt/compile.h>
consteval auto example(unsigned i) -> std::array<char, 16> {
auto result = std::array<char, 16>();
fmt::format_to(result.data(), FMT_COMPILE("You sent {}"), i);
return result;
}
constexpr auto result = example(42);
This gives an array rather than a string_view but you can make one from the other.
Godbolt: https://godbolt.org/z/TqoEfTfWs

std::string aware options for vsprintf

I have an old MUD codebase in C (>80k lines) that uses printf-style string formatting. It is pervasive -- almost every bit of text runs through calls to either sprintf or a wrapper around vsprintf. However, I have recently moved to compiling with g++ to take advantage of the STL, and would like to use std::string (actually a derived class for default case-insensitive comparisons) where it makes sense.
Obviously, you can't pass std::string as one of the variadic arguments to any of the printf functions: I need .c_str() in every case. I don't want to do that, mostly because I don't want to modify 2000+ calls to printf functions. My question is: how can I make a std::string aware vsprintf?
The way I see it, I have two options: write my own printf functions that iterate through the arguments changing pointers to std::string to std::string.data (or c_out()) before passing to std::vsprintf, or I can borrow the guts of printf and roll my own. The first option sounds like less work, obviously.
Of course, a better option is if someone has done this before, but my googling is yielding nothing. Any tips on what the best option would look like?
EDIT:
This question was closed as a duplicate of How to use C++ std::ostream with printf-like formatting?, which I don't believe answers the question. I'm not asking how to output strings with std::ostream vs the old C printf. I'm asking for help with a patch solution for an old C codebase that makes extensive use of sprintf/vsprintf, without rewriting thousands of calls to those functions to use output streams.
You can make your own printf wrapper, that extracts char const* from std::string. E.g.:
#include <iostream>
#include <string>
#include <cstdio>
template<class T>
inline auto to_c(T&& arg) -> decltype(std::forward<T>(arg)) {
return std::forward<T>(arg);
}
inline char const* to_c(std::string const& s) { return s.c_str(); }
inline char const* to_c(std::string& s) { return s.c_str(); }
template<class... Args>
int my_printf(char const* fmt, Args&&... args) {
return std::printf(fmt, to_c(args)...);
}
int main() {
std::string name = "World";
my_printf("Hello, %s!\n", name);
}
Or, better, switch to a modern C++ formatting library, such as fmt.
The common advice is Boost.Format
Taking their example:
// printf directives's type-flag can be used to pass formatting options :
std::cout << format("_%1$4d_ is : _%1$#4x_, _%1$#4o_, and _%1$s_ by default\n") % 18;
// prints "_ 18_ is : _0x12_, _ 022_, and _18_ by default\n"
Now this assumes std::ostream&, so you'll need a std::stringstream to use a std::string as the backing buffer.
PS. using a derived class for case-insensitive comparisons sounds like a bad idea waiting to bite you. You just need a custom order; all the STL functions that assume ordering have overloads to support custom orderings.

Get a char from a pointer to a string

Hello I am trying to write a function that converts a string to lowercase by using a pointer instead of a return value.
void makeLowerCase(std::string* in){
//for loop tolower(char from *in);}
but I have no idea how to get each char out of my pointer to use tolower() with, or how to get how many chars are in the string as
*in.length()
and
sizeof(*in)/sizeof(char)
don't work for it. The former I get an error on the use of a pointer, the latter I get the same return value for sizeof(*in) so I don't even know how I would end my for loop.
C++ has a shortcut to get the member of an object pointed to by a pointer:
in->length()
For accessing characters, use parentheses:
(*in)[i]
Instead of passing by pointer and dealing with pointer syntax you can pass the string by reference and then you can use it just like a normal std::string. If you have to use a pointer then you can either use
in->length();
or
(*in).length();
The parentheses are required in the second case as . has a higher precedence then *.
As for transforming the string to lower case you can use the built in functions from <algorithm> and and that would give you
void makeLowerCase(std::string& in)
{
std::transform(in.begin(), in.end(), in.begin(), ::tolower);
}
*in.length()
does not work because . has a higher precedence than *. Use parantheses:
(*in).length()
sizeof(*in)/sizeof(char)
is the same as
sizeof(*in) / 1
because sizeof(char) == 1. sizeof(*in) == sizeof(std::string), so this yields the size of the std::string object itsself, not the string of characters, which is implemention-defined.
This information, in combination with iterators, for_each, and lambdas, make for a pretty three-liner without any functions:
#include <cctype>
...
for (char& c : str)
c = std::tolower(c);
Notes:
Use references instead. They look better and are easier usable. Pointers should only be used in C++ for low-level stuff or when there's no way to cut them out.
For pointers you would use the pointer operator. So that would be
in->length();
However a naked loop is not the ideal way (nor is using pointers to be honest).
A better way would be to use iterators to iterate through the string and convert it that way.
for (auto it=in->begin(); it!=in->end(); ++it) {
*it = std::tolower(*it);
}

Piping from Istringstream into templates

I have the following questions: I have a map from string to string which is called psMap. I.e. psMap["a"]="20", psMap["b"]="test", psMap["c"]="12.5", psMap["d"]="1" (true) so the map stores string-expressions of various basic-data types.
The following function foo should (given a key), copy the mapped value to a corresponding type variable, i.e;
int aa;
foo("a", aa);
=> aa=20.
Explicitly, I want to have one function for all possible data-types (so no manually cast), so I tried with templates exploiting the automatic conversion of istringsteram, namely
template<class PARAMTYPE>
void foo(string _name, PARAMTYPE& _dataType) {
PARAMTYPE buff;
istringstream(psMap[_name]) >> buff;
_dataType = buff;
}
The problem is, that the ">>" operation gives an error: Error: no match for »operator>>« in »std::basic_stringstream<char>((* ....
What is going wrong here? Does the stringstream not recognize the correct data type and tries to pipe into an abstract type of "template"? How could I make my code work?
Tank you for your effort :)
You've created a temporary std::istream, which means that it
cannot bind to a non-const reference. Some of the >> are
member functions, and they will work, but others are free
functions with the signature:
std::istream& operator>>( std::istream&, TargetType& );
and these will not work (or even compile).
To avoid the problem either Just declare an std::istringstream
and use it, or call a member function on the temporary which
does nothing, but returns a (non-const) reference:
std::istringstream( psMap[name] ).ignore(0) >> buff;
(Personally, I find the separate variable more readable.)
You use reference as the template argument, so if you call
foo("a", aa);
without '& it should be fine (the way you tried the operator>> for pointer was needed). You also need to modify the last template line:
_dataType = buff;
Try this implementation:
template<class R>
R get_value(const std::string& name) {
R result{};
std::istringstream buffer{psMap[name]};
buffer >> result;
return result;
}
client code:
int x = get_value<int>("a");
Also, do not use identifiers starting with an underscore. That is reserved for library implementers.

Using templates for implementing a generic string parser

I am trying to come up with a generic solution for parsing strings (with a given format). For instance, I would like to be able to parse a string containing a list of numeric values (integers or floats) and return a std::vector. This is what I have so far:
template<typename T, typename U>
T parse_value(const U& u) {
throw std::runtime_error("no parser available");
}
template<typename T>
std::vector<T> parse_value(const std::string& s) {
std::vector<std::string> parts;
boost::split(parts, s, boost::is_any_of(","));
std::vector<T> res;
std::transform(parts.begin(), parts.end(), std::back_inserter(res),
[](const std::string& s) { return boost::lexical_cast<T>(s); });
return res;
}
Additionally, I would like to be able to parse strings containing other type of values. For instance:
struct Foo { /* ... */ };
template<>
Foo parse_value(const std::string& s) {
/* parse string and return a Foo object */
}
The reason to maintain a single "hierarchy" of parse_value functions is because, sometimes, I want to parse an optional value (which may exist or not), using boost::optional. Ideally, I would like to have just a single parse_optional_value function that would delegate on the corresponding parse_value function:
template<typename T>
boost::optional<T> parse_optional_value(const boost::optional<std::string>& s) {
if (!s) return boost::optional<T>();
return boost::optional<T>(parse_value<T>(*s));
}
So far, my current solution does not work (the compiler cannot deduce the exact function to use). I guess the problem is that my solution relies on deducing the template value based on the return type of parse_value functions. I am not really sure how to fix this (or even whether it is possible to fix it, since the design approach could just be totally flawed). Does anyone know a way to solve what I am trying to do? I would really appreciate if you could just point me to a possible way to address the issues that I am having with my current implementation. BTW, I am definitely open to completely different ideas for solving this problem too.
You cannot overload functions based on return value [1]. This is precisely why the standard IO library uses the construct:
std::cin >> a >> b;
which may not be your piece of cake -- many people don't like it, and it is truly not without its problems -- but it does a nice job of providing a target type to the parser. It also has the advantage over a static parse<X>(const std::string&) prototype that it allows for chaining and streaming, as above. Sometimes that's not needed, but in many parsing contexts it is essential, and the use of operator>> is actually a pretty cool syntax. [2]
The standard library doesn't do what would be far and away the coolest thing, which is to skip string constants scanf style and allow interleaved reading.
vector<int> integers;
std::cin >> "[" >> interleave(integers, ",") >> "]";
However, that could be defined. (Possibly it would be better to use an explicit wrapper around the string literals, but actually I prefer it like that; but if you were passing a variable you'd want to use a wrapper).
[1] With the new auto declaration, the reason for this becomes even clearer.
[2] IO manipulators, on the other hand, are a cruel joke. And error handling is pathetic. But you can't have everything.
Here is an example of libsass parser:
const char* interpolant(const char* src) {
return recursive_scopes< exactly<hash_lbrace>, exactly<rbrace> >(src);
}
// Match a single character literal.
// Regex equivalent: /(?:x)/
template <char chr>
const char* exactly(const char* src) {
return *src == chr ? src + 1 : 0;
}
where rules could be passed into the lex method.