I have the following trim function
std::string trim(const std::string& str, std::function<bool(int ch)> isCharToTrim)
{
auto trimmedStart = std::find_if_not(str.begin(), str.end(), isCharToTrim);
if (trimmedStart == str.end())
{
return "";
}
else
{
auto trimmedEnd = std::find_if_not(str.rbegin(), str.rend(), isCharToTrim);
return std::string(trimmedStart, trimmedEnd.base());
}
}
When I pass std::isspace as second argument, it compiles with MSVC.
But I get an error with gcc: error: cannot resolve overloaded function 'isspace' based on conversion to type 'std::function<bool(int)>'.
Usage of the function that works on MSVC
const auto trimmed = trim(test, std::isspace);
const auto trimmed2 = trim(test, std::not_fn(std::isgraph));
const auto trimmed3 = trim(test, [](int ch) { return ch == ' '; });
What changes can I make to get it to compile on gcc? Change the argument type?
https://godbolt.org/z/81cjvrh7E
You should not use function pointers to functions in the standard library unless they are explicitly addressable functions.
You can wrap them in a lambda:
const auto trimmed = trim(test, [](auto c) { return std::isspace(static_cast<unsigned char>(c)); });
Note that it is not necessary to convert all callables to std::function just to call them or pass them to an algorithm. You can accept any callable by making the function a template:
template <typename C>
std::string trim(const std::string& str, C isCharToTrim);
The error complains about an overload because there is https://en.cppreference.com/w/cpp/locale/isspace in addition to the function you want to pass. Anyhow, strictly speaking the standard merely specifies what happens when you call std::isspace(int). There needs not actually be a function int std::isspace(int), it could be int std::isspace(int,int=42). There can be other overloads present. For this (and perhaps other) reasons it is generally not allowed to take pointers to standard functions.
Related
I have the following code:
#include <variant>
#include <string>
#include <iostream>
using Variant = std::variant<double, std::string>;
// helper type for the visitor
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
// explicit deduction guide (not needed as of C++20)
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
std::string string_from(const Variant& v)
{
return std::visit(overloaded {
[](const double arg) { return std::to_string(arg); },
[](const std::string& arg) { return arg; },
}, v);
}
int main()
{
Variant v1 {"Hello"};
Variant v2 {1.23};
std::cout << string_from(v1) << '\n';
std::cout << string_from(v2) << '\n';
return 0;
}
I have a function called string_from() which takes a variant and converts its inner value to a string.
The variant can hold either a std::string or a double.
In case of a std::string, I just return it.
In case of a double, I create a std::string from the double and then return it.
The problem is, I don't like the fact that I'm returning a copy of the std::string in case of a string-variant. Ideally, I would return a std::string_view or another kind of string observer.
However, I cannot return a std::string_view because in case of a double-variant I need to create a new temporary std::string and std::string_view is non-owning.
I cannot return a std::string& for the same reason.
I'm wondering if there's a way to optimize the code so that I can avoid the copy in case of a string-variant.
Note in my actual use case, I obtain strings from string-variants very frequently, but very rarely from double-variants.
But I still want to be able to obtain a std::string from a double-variant.
Also, in my actual use case, I usually just observe the string, so I don't really need the copy every time. std::string_view or some other string-observer would be perfect in this case, but it is impossible due to the reasons above.
I've considered several possible solutions, but I don't like any of them:
return a char* instead of a std::string and allocate the c-string somewhere on the heap in case of a double. In this case, I would also need to wrap the whole thing in a class which owns the heap-allocated strings to avoid memory leaks.
return a std::unique_ptr<std::string> with a custom deleter which would cleanup the heap-allocated strings, but would do nothing in case the string resides in the variant. Not sure how this custom deleter would be implemented.
Change the variant so it holds a std::shared_ptr<std::string> instead. Then when I need a string from the string-variant I just return a copy of the shared_ptr and when I need a string from the double-variant I call std::make_shared().
The third solution has an inherent problem: the std::string no longer resides in the variant, which means chasing pointers and losing performance.
Can you propose any other solutions to this problem? Something which performs better than copying a std::string every time I call the function.
You can return a proxy object. (this is like your unique_ptr method)
struct view_as_string{
view_as_string(const std::variant<double, std::string>& v){
auto s = std::get_if<std::string>(&v);
if(s) ref = s;
else temp = std::to_string(std::get<double>(v));
}
const std::string& data(){return ref?*ref:temp;}
const std::string* ref = nullptr;
std::string temp;
};
Use
int main()
{
std::variant<double, std::string> v1 {"Hello"};
std::variant<double, std::string> v2 {1.23};
std::cout << view_as_string(v1).data() << '\n';
view_as_string v2s(v2);
std::cout << v2s.data() << '\n';
}
The problem is, a variant holds different types, but you're trying to find a way to represent all of them in a single type. A string representation is useful for generic logging, but it has the downsides you describe.
For variants, I don't like trying to consolidate the values back into a single common thing, because if that was easily possible then there would be no need for the variant in the first place.
Better, I think, is to defer the conversion as late as possible, and keep forwarding it on to other functions that make use of the value as it is, or convert and forward until it's used--rather than trying to extract a single value and trying to use that.
A fairly generic function might look like this:
template <typename Variant, typename Handler>
auto with_string_view(Variant const & variant, Handler && handler) {
return std::visit(overloaded{
[&](auto const & obj) {
using std::to_string;
return handler(to_string(obj));
},
[&](std::string const & str) {return handler(str); },
[&](std::string_view str) { return handler(str); },
[&](char const * str) { return handler(str); }
}, variant);
}
Since the temporary created in the generic version outlives the call to the handler, this is safe and efficient. It also shows the "forward it on" technique that I've found to be very useful with variants (and visiting in general, even for non-variants.)
Also, I don't explicitly convert to string_view, but the function could add requirements that the handler accepts string views (if that helps document the usage.)
With the above helper function you might use it like this:
using V = std::variant<std::string, double>;
V v1{4.567};
V v2{"foo"};
auto print = [](std::string_view sv) { std::cout << sv << "\n";};
with_string_view(v1, print);
with_string_view(v2, print);
Here's a full live example, expanded out a little too: https://godbolt.org/z/n7KhEW7vY
If thread safety is not an issue, you could simply use a static std::string as the backing storage when returning a double value. Then you would be able to return a std::string_view, eg:
std::string_view string_from(const Variant& v)
{
static std::string buffer;
return std::visit(overloaded {
[&buffer](const double arg) -> std::string_view { buffer = std::to_string(arg); return buffer; },
[](const std::string& arg) -> std::string_view { return arg; },
}, v);
}
Online Demo
I've come up with my own solution inspired by apple apple's solution with the view_as_string class.
Here it is:
class owning_string_view : public std::string_view
{
public:
explicit owning_string_view(const char* str) : std::string_view{str}, m_string_buffer{} {}
explicit owning_string_view(const std::string& str) : std::string_view{str}, m_string_buffer{} {}
explicit owning_string_view(std::string&& str) : std::string_view{}, m_string_buffer{std::move(str)}
{
static_cast<std::string_view&>(*this) = m_string_buffer;
}
private:
std::string m_string_buffer;
};
Instead of taking a Variant I made it more generic and it takes strings instead.
For lvalue strings it just creates a std::string_view of the string.
For rvalue strings it moves the string into the buffer.
It extends from std::string_view so it can be used in std::string_view contexts seamlessly.
Of course you have to be careful not no slice off the std::string_view part from the object when creating an rvalue owning_string_view but this is true for std::string_view as well. You have to be careful not to take a std::string_view from an rvalue std::string.
Passing a owning_string_view as a std::string_view parameter to a function is safe for the same reason it is safe to pass an rvalue std::string as a std::string_view parameter to a function. The rvalue lives during the function call.
I also realized a deeper problem when returning a string_view from my Variantclass.
If I try to extract a std::string_view or a owning_string_view from an rvalue Variant I'm still going do end up with a dangling string_view, so I added 2 functions for taking a string from the Variant:
one accepts lvalue variants only and it returns owning_string_view.
the other accepts rvalue variants only and it returns a std::string, which is moved from the variant (since the variant is an rvalue).
One more observation: Ideally, I would make the first 2 constructors of owning_string_view constexpr but I can't because the default constructor of std::string is not constexpr. I hope this is changed in the future.
I need to convert a string that represents a vector of Ts into the corresponding vector.
My problem is that I'd like to pass a simple argument: the converter function. Here's the split:
template <class T>
auto split(const std::string &s, const std::function<T(const std::string&)> &convert, char sep = ',') -> std::vector<T>
{
std::stringstream ss(s);
std::vector<T> result;
while (ss.good())
{
std::string substr;
std::getline(ss, substr, sep);
if (!substr.empty())
result.push_back(convert(substr));
}
return result;
};
It fails to compile when passing standard functions such as std::stoi because of the default parameters of std::stoi as its signature is int stoi(const string& __str, size_t* __idx = 0, int __base = 10);:
auto q = split<int>(subs, std::stoi);
error: no matching function for call to 'split'
auto q = split<int>(subs, std::stoi);
^~~~~~~~~~
And obviously I can trick the compiler by using a lambda function:
auto q = split<std::size_t>(subs, [](const std::string &s){ return std::stoul(s); });
Is there a metaprogramming trick that allows me to somehow ignore the default parameters?
EDIT: This doesn’t actually help in this case. I’m leaving it because it’s useful in some other cases, such as if you had a function which returned something convertible to T, but it doesn’t address any of the issues with stoi.
Don’t explicitly specify the type of the function. Let convert be any type; you’ll get an error if you try passing something which cannot be called on a std::string or which doesn’t return something convertible to a T. There’s no reason to constrain the type beyond that unless you specifically have a reason it needs to be that specific type, and in this case you don’t.
Thus, you can declare your function as
template <class T, class F>
auto split(const std::string &s, const F&& convert, char sep = ',') -> std::vector<T>
#define RETURNS(...) \
noexcept(noexcept(__VA_ARGS__)) \
-> decltype( __VA_ARGS__ ) \
{ return __VA_ARGS__; }
#define OVERLOADS_OF(...) \
[](auto&&...args) \
RETURNS( __VA_ARGS__( decltype(args)(args)... )
This macro lets you take the name of a function and generate a lambda that contains the overloads of it.
auto q = split<std::size_t>( subs, OVERLOADS_OF(std::stroul) );
which is nice and concise.
Default arguments are only accessible by invoking () on the actual name of the function, and the only way to "move the name" into a different context is to stuff it into a lambda as text.
As an aside, there is a c++2a proposal by #barry to replace RETURNS(X) above with => X for lambdas. I am unaware of a currently maintained proposal to replace the OVERLOADS_OF macro (there was one a while back).
Possibly the c++2a reflection proposal would permit you to gain access to the default arguments and overload set of a function name, and fancy metaprogramming would then let you generate OVERLOADS_OF without a macro.
I have a function which takes an "auto" and returns an "auto". This function takes numeric types (eg, complex, int, or doubles). However, depending on the result of the function, I need to return something explicitly. For example, if a complex number is passed to the function, I need to return "complex(0, 0)" if the "real" part of the number is less than zero. The code looks something like the following:
if(myNumber<0){ return 0.0;} else{ return myNumber; }
Now of course I have to overload the "less than" operator but the difficult part is how to allow returning 0 when myNumber is not a double. I have overloaded the "=" operator to allow assignment of doubles to complex numbers, however I still get compiling errors.
Is there any good way to accomplish this?
Edit:
My complete code looks like the following.
auto BSCall(const auto &S0, const auto &k, const auto &discount, const auto &sigma){
if(sigma<=0){
return 0.0;
}
else{
double s=sqrt(2.0);
auto d1=log(S0/(discount*k))/(sigma)+sigma*.5;
return S0*(.5+.5*erf(d1/s))-k*discount*(.5+.5*(erf((d1-sigma)/s)));
}}
Edit again:
It turns out that I didn't have my class have a constructor which took a double. My code works when I have both the operator "=" overloaded AND a constructor which has a single double.
I see two ways:
First is to try initializer list:
if(myNumber<0){
return {}; // <= it means you return T()
}else{
return myNumber;
}
Second is to use std::result_of from type_traits header.
if(myNumber<0){
return std::result_of<YourFunctionReference>::type();
}else{
return myNumber;
}
Of course your function is templated so I'm not quite sure if second way will work. Please post additional code from your project so I will be able to tell you how to use std::result_of in your case.
I think you are running into issues because you have two returns that are returning different types, and the compiler can't decide which type to use as the return type.
You can get around this by putting your calculation into a helper function:
auto BSCallHelper(
const auto &S0,
const auto &k,
const auto &discount,
const auto &sigma
)
{
double s=sqrt(2.0);
auto d1=log(S0/(discount*k))/(sigma)+sigma*.5;
return S0*(.5+.5*erf(d1/s))-k*discount*(.5+.5*(erf((d1-sigma)/s)));
}
Then you can use the helper function to make your return type be explicit:
auto BSCall(
const auto &S0,
const auto &k,
const auto &discount,
const auto &sigma
) -> decltype(BSCallHelper(S0,k,discount,sigma))
{
if(sigma<=0){
return 0.0;
}
return BSCallHelper(S0,k,discount,sigma);
}
You can also use the ?: operator to resolve a common type:
auto BSCall(
const auto &S0,
const auto &k,
const auto &discount,
const auto &sigma
)
{
return (sigma<=0) ? 0 : BSCallHelper(S0,k,discount,sigma);
}
I'd like to start by saying that yes, I Google'd this problem before coming here, and none of the answers seemed relevant.
I stole the below code from What's the best way to trim std::string?, because for whatever reason, there is no standard c++ trim function. Using Visual Studio, it compiled fine, and I managed to complete the rest of the project without it giving me any errors.
This morning though, I decided to try compiling the entire project manually (using g++ -std=c++11 *.cpp), and now suddenly the trim functions are yielding the following error:
DVD.cpp: In static member function 'static DVD DVD::parseDVD(std::string, std::string)':
DVD.cpp:65:59: error: invalid initialization of non-const reference of type 'std::string& {aka std::basic_string<char>&}
from an rvalue of type 'std::basic_string<char>'
std::string rID = trim(dataStr.substr(0, preTitlePos - 1));
It yields similar errors for the other 2 times that trim is used.
Here is the "stolen" code:
(Utils.h):
static inline std::string& ltrim(std::string& s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
return s;
}
// trim from end
static inline std::string& rtrim(std::string& s) {
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
return s;
}
// trim from both ends
static inline std::string& trim(std::string& s) {
return ltrim(rtrim(s));
}
And here is the parseDVD function that the error mentions:
(DVD.cpp):
DVD DVD::parseDVD(std::string dataStr, std::string delimiter) {
DVD newDVD;
int preTitlePos = dataStr.find(delimiter, 0);
int preGenrePos = dataStr.find(delimiter, preTitlePos + 1);
// V Error is here V
std::string rID = trim(dataStr.substr(0, preTitlePos - 1));
std::string rTitle = trim(dataStr.substr(preTitlePos + 1, preGenrePos - preTitlePos - 1));
std::string rGenre = trim(dataStr.substr(preGenrePos + 1));
int parsedID = 0;
//Requirements for a successful parse
//The ID must be fully numeric, and both of the delimiters must have been found
if (parseInt(rID, parsedID) && preTitlePos > -1 && preGenrePos > -1) {
return
newDVD .setID(parsedID)
.setTitle(rTitle)
.setGenre(rGenre);
}
return badDVD;
}
If I remove all of the &s from the trim functions, it works, but I'd rather it not make copies constantly.
This baffles me because I know the code is sound; not only is it the accepted answer to the above question, but it works fine in Visual Studio.
Your trim() function is expecting a non-const reference to a std::string. When you invoke it like this:
std::string rID = trim(dataStr.substr(0, preTitlePos - 1));
You are invoking it with an rvalue, an unnamed temporary. This will have type const std::string &, so it is not compatible with the trim() function. In order to make it work, you would need to assign it to a named variable first:
std::string temp = dataStr.substr(0, preTitlePos - 1);
std::string rID = trim(temp);
On a side note, you seem to be mixing two methods of returning outputs from the trim() function. Typically, one will either return the function's result (usually by value), or one will modify arguments that were passed to the function by reference. Your functions do both, which is not typical.
I would change them to either take an input argument and return the result by value, or modify the by-reference argument that you pass in (and change their return types to void).
I want to write a C++11 function that will only accept string literals as a parameter:
void f(const char* s) { static_assert(s is a string literal); ... }
That is:
f("foo"); // OK
char c = ...;
f(&c); // ERROR: Doesn't compile
string s = ...;
f(s.c_str()); // ERROR: Doesn't compile
etc
Is there anyway to implement this? The signature of the function is open to changes, as is adding the use of macros or any other language feature.
If this is not possible what is the closest approximation? (Can user-defined literals help in anyway?)
If not is there a platform specific way in GCC 4.7 / Linux ?
I think the closest you are going to get is this
template<int N>
void f(const char (&str)[N]){
...
}
It will compile with literals and arrays but not pointers.
An alternative might be to make a GCC extension to check at compile time that your particular function is only called with a literal string.
You could use MELT to extend GCC. MELT is a high-level domain specific language to extend the GCC compiler, and is very well suited for the kind of check you want.
Basically, you would add a new pass inside GCC and code that pass in MELT which would find every gimple which is a call to your function and check that the argument is indeed a literal string. The ex06 example on melt-examples should inspire you. Then subscribe to gcc-melt#googlegroups.com and ask your MELT specific questions there.
Of course, this is not a foolproof approach: the function could be called indirectly thru pointers, and it could e.g. have a partial literal string, e.g. f("hello world I am here"+(i%4)) is conceptually a call with some literal string (e.g. in .rodata segment), but not in the generated code nor in the gimple.
I use this :
// these are used to force constant, literal strings in sqfish binding names
// which allows to store/copy just the pointer without having to manage
// allocations and memory copies
struct _literalstring
{
// these functions are just for easy usage... not needed
// the struct can be empty
bool equal(_literalstring const *other) { return !strcmp((const char *)this, (const char *)other); }
bool equal(const char *other) { return !strcmp((const char *)this, other); }
const char *str(void) { return (const char *)this; }
bool empty(void) { return *(const char *)this == 0; }
};
typedef _literalstring *LITSTR;
constexpr LITSTR operator "" _LIT(const char *s, size_t) {
return (LITSTR)s;
}
Then you just declare your function like this :
void myFunc(LITSTR str)
{
printf("%s\n", str->str());
printf("%s\n", (const char *)str);
const char *aVar = str->str();
const char *another = (const char *)str;
}
And you call it like this:
myFunc("some text"_LIT);
If you do something like this:
myFunc("some text");
myFunc(aTextVariable);
you get a compiler error.