I have a function whose signature is:
void func(std::optional<std::string> os = std::nullopt);
(I’m aliasing std::experimental::optional until std::optional is officially available.)
However, I’m having difficulty calling it cleanly. The compiler will refuse to perform two implicit conversions (const char* ➝ std::string ➝ std::optional<std::string>) to call it with a raw C-string literal. I can do this:
func(std::string("Hello"));
And the compiler will figure that a std::optional is needed, and do the conversion. However, this is way too verbose. Thanks to C++11, I can also do this:
func({"Hello"});
While this is way better, it's still not ideal. I'd like to be able to call this function like any other that takes a std::string. Is this possible? Making the function take another parameter type is okay, as long as it behaves similarly to/is directly convertible to std::optional. Thanks.
C++14 adds a bunch of user-defined literals to the standard library in order to make code less verbose. It looks something like this:
using namespace std::string_literals; // needed
// using namespace std::literals; // also ok, but unnecessary
// using namespace std::literals::string_literals; // also ok, but why??
int main()
{
std::string str = "string"s;
^^^^^^^^
// This is a std::string literal,
// so std::string's copy constructor is called in this case
}
Also take a look at this and this for reference.
You can do that with a bit of templates and sfinae:
template<typename T, std::enable_if_t<
std::is_constructible<std::string, T>::value &&
!std::is_constructible<std::optional<std::string>, T>::value>* = nullptr>
void func(T&& s) {
void func(std::string(std::forward<T>(s)));
}
This overload will be picked when a string would be constructible with a forwarded T but only when std::optional<std::string> is not constructible.
You function will be callable with any object that a string can be constructed with:
func("potato"); // working, forward the string literal to a std::string
Related
I would like to make a universal wrapper function which can accept any
free standing or static function,
member function ( perhaps as a specialization with the first argument used as *this)
including overloaded or templated cases together with variable arguments. Such wrapper will then, in the body, call the function exactly with the forwarded parameters.
Example:
template<typename Fnc,typename...Args>
void wrapper(Fnc fnc, Args&&...args){
// Do some stuff
// Please disregard the case when return type is void,
// that be SFINAED with std::result_of.
auto res = fnc(std::forward<Args>(args)...);
// Do some stuff
return res;
}
#include <vector>
auto foo(int i){ return i; }
auto foo(double& d){ return d; }
auto foo(double&& d){ return d; }
auto foo(const char* str){ return str; }
template<typename...T>
auto generic_foo(T&&...ts){/* ...*/ return /* ...*/; }
template<typename T>
void constrained_foo(std::vector<T>& lref,std::vector<T>&& rref, std::vector<T> value){ /**/}
int main(){
// Basics
wrapper(foo, 1);// foo(int)
wrapper(foo, 1.1); // foo(double&&)
wrapper(foo, "ahoj"); // foo(const char*)
// Conversion must work too
wrapper(foo, 1.1f); // foo(double&&)
wrapper(foo, (short)1); // foo(int)
// Detecting lvalues, rvalues is also a must
double y;
foo(y);
foo(std::move(y));
// Similarly for templates
int x;
std::vector<int> v1, v2, v3;
wrapper(generic_foo, 1, 1.1, "ahoj", x, &x);
wrapper(constrained_foo, v1, std::move(v2), v3);
}
The thing I do find so frustrating about this is that I am supplying all the necessary information to make these calls right next to each other, there is no added ambiguity about what to call, I could call it myself, I could(will) make a macro that can do it, but there is no proper C++ syntax for it AFAIK.
I discovered the need for it while trying to automatically call all my methods in certain "context". But thinking about it more, I believe this could have really widespread usage for <algorithm>, <thread> libraries too. Where you would not have to make one-statement lambdas just to call a function/operator with the lambdas parameters or something captured.
The issue arises in any function accepting another function which will be eventually called together with the passed known parameters.
My attempts
generic_foo can be resolved if the return type is fixed:
template<typename...Args>
void wrapper(void(*f)(Args&&... args) , Args&&...args){
// ...
f(std::forward<Args>(args)...);
}
int main(){
int x;
wrapper(generic_foo, 1, 1.1, "ahoj", x, &x, std::move(x));
}
This works nicely, the return type can maybe be resolved too by some obscure and clever use of std::invoke_result_t, but currently it is a kind of chicken-egg situation with the parameter type. Because the only thing how to resolve the name generic_foo is to force it to decay to a function pointer and then there is no name to put in std::invoke_result_t since the parameter is still being deduced.
This will also work with overloads as long as there is an exact match, so it cannot do conversions.
This approach is as far as I can get without macros when the function name is not known in advance.
If the name of the callable is fixed, there is this frequently-used variation of lambda trick:
template<typename Fnc, typename...Args>
void wrapper(Fnc f , Args&&...args){
// ...
f(std::forward<Args>(args)...);
}
int main(){
int x;
wrapper([](auto&&...args)
{ return generic_foo(std::forward<decltype(args)>(args)...);},
1, 1.1, "ahoj", x, &x, std::move(x));
}
If I add a macro doing exactly this:
#define WRAP_CALL(wrapper_fnc, called_fnc, ...) \
wrapper_fnc([&](auto&&...args) \
{ return called_fnc(std::forward<decltype(args)>(args)...);}, \
__VA_ARGS__ );
int main(){
int x;
WRAP_CALL(wrapper, generic_foo, 1, 1.1, "ahoj", x, &x, std::move(x))
}
I get the least macro-infested working solution I can think of, it works with any callable and any wrappers which can stay proper C++ functions. But I would like macro-less version of this and especially for functions.
So I will probably still use this version, does not seem too unreasonable. Are there any corners cases I should know about?
I did not write a single C++20 concept yet, so I still have very small hope there might be something that can work in that area perhaps? But probably not since std::thread(foo,1); also suffers from it.
So this might sadly require language changes because the name of the overload set or a template cannot currently be passed anywhere, even just as some kind of aggregated type. So perhaps something akin to std::initializer_list class plus its sometimes-magical syntax?
If this is indeed the case, I would gladly accept any answer listing any currently active proposals that might help with this. If there are even any.
I did found N3579 - A Type trait for signatures which could perhaps work together with the function pointer solution if the chicken-egg problem is addressed. But the proposal looks very dead.
The "overloaded or templated cases" are not entities that can be function/template arguments—certain cases where overload resolution can use contextual information notwithstanding. What you mean by foo in your wrapper(foo,…) is little more than a token (in particular, it's an overload set), and the language simply has no way of addressing such an object since it has no ("aggregated"?) type. (Conversely, macros do operate on tokens, which is why they are applicable here.) You seem to know most of this, but it may be helpful to see why it's knowably impossible, and why it's a bad idea to think of an overload set as "a callable". (After all, syntactically a type name is also "callable", but it wouldn't make any sense to pass one as a function argument.)
Even if a call f(g,…) were defined to try each overload of g in turn (which it is, for the narrow purpose of deducing f's template arguments), that wouldn't help for (an overload set containing) a template: there would be no way to even evaluate f's SFINAE conditions given a g template for which a specialization had not yet been chosen.
The standard lambda trick, which you also illustrated, is a way of performing overload resolution with the benefit of the argument list, which is why it's pretty much the only approach that works. There are certainly proposals to automate that process, including the vagaries of SFINAE-friendliness and exception specifications.
Consider this instead:
template <class T>
auto wrapper(T fnc) {
// Do some stuff
auto res = fnc(); // <--- no arguments
// Do more stuff
return res;
}
Since arguments are known at wrapper call time, they can also be bound at wrapper call time.
wrapper([](){ return foo(1); });
wrapper([](){ return foo(1.1); });
wrapper([](){ return foo("ahoj"); });
wrapper([&x](){ return generic_foo(1, 1.1, "ahoj", x, &x); });
You can encapsulate this in a macro, which is of course less than ideal, but at least this one is short and readable.
#define DEFER(x) ([&](){return x;})
wrapper(DEFER(foo(1)));
wrapper(DEFER(foo(1.1)));
wrapper(DEFER(foo("ahoj")));
wrapper(DEFER(generic_foo(1, 1.1, "ahoj", x, &x)));
This doesn't do exactly what you want, for example, in
wrapper(DEFER(foo(bar())))
bar is called late. This is fixable with a bit of syntax:
wrapper([z=bar()](){ return foo(z); });
and of course this can be wrapped in a macro too:
wrapper(DEFER1(foo(z), z=bar()));
although this is getting a bit unwieldy.
I'd like to know if C++ 'auto' is smart enough to pass by reference for [in] parameters. For example:
void PrintString(auto string1)
{
std::string msg;
msg = string1 + "\n";
printf("%s\n", msg.c_str());
}
Is auto smart enough to deduce string1 type to a const ref type like this?
void PrintString(const std::string &string1)
or does it just deduce to inefficient pass-by-value?
void PrintString(std::string string1)
auto as applied to function parameters is illegal in C++11, so your question is moot.
C++14 allows lambda functions to use auto in parameters. But this is done by making the lambda's generated operator() a template. So [](auto val) is equivalent to template<typename T> void some_func(T val);. And just like any other instance of a template, val is not a reference unless T is itself a reference type. The rules of template argument deduction don't change just because you used auto rather than an explicit template argument.
The same will be true when/if C++20 formally allows auto to work on all functions. And compilers which offer auto parameters on non-lambdas as a compiler extension are doing it exactly as they would for lambdas.
Is auto smart enough to deduce string1 type to a const ref type like this?
What about this would be "smart"? The user didn't ask for a const& parameter, as evidenced by the lack of const and the lack of &. If a user genuinely wants the so-called "inefficient" version (which is a perfectly valid thing to do), then such code would not be smart. Indeed, under your "smart" version, you would be unable to write a function that took std::string by value.
I currently have a map<int, std::wstring>, but for flexibility, I want to be able to assign a lambda expression, returning std::wstring as value in the map.
So I created this template class:
template <typename T>
class ValueOrFunction
{
private:
std::function<T()> m_func;
public:
ValueOrFunction() : m_func(std::function<T()>()) {}
ValueOrFunction(std::function<T()> func) : m_func(func) {}
T operator()() { return m_func(); }
ValueOrFunction& operator= (const T& other)
{
m_func = [other]() -> T { return other; };
return *this;
}
};
and use it like:
typedef ValueOrFunction<std::wstring> ConfigurationValue;
std::map<int, ConfigurationValue> mymap;
mymap[123] = ConfigurationValue([]() -> std::wstring { return L"test"; });
mymap[124] = L"blablabla";
std::wcout << mymap[123]().c_str() << std::endl; // outputs "test"
std::wcout << mymap[124]().c_str() << std::endl; // outputs "blablabla"
Now, I don't want to use the constructor for wrapping the lambda, so I decided to add a second assignment operator, this time for the std::function:
ValueOrFunction& operator= (const std::function<T()>& other)
{
m_func = other;
return *this;
}
This is the point where the compiler starts complaining. The line mymap[124] = L"blablabla"; suddenly results in this error:
error C2593: 'operator = is ambiguous'
IntelliSense gives some more info:
more than one operator "=" matches these operands: function
"ValueOrFunction::operator=(const std::function &other) [with
T=std::wstring]" function "ValueOrFunction::operator=(const T
&other) [with T=std::wstring]" operand types are: ConfigurationValue =
const wchar_t
[10] c:\projects\beta\CppTest\CppTest\CppTest.cpp 37 13 CppTest
So, my question is, why isn't the compiler able to distinguish between std::function<T()> and T? And how can I fix this?
The basic problem is that std::function has a greedy implicit constructor that will attempt to convert anything, and only fail to compile in the body. So if you want to overload with it, either no conversion to the alternative can be allowed, of you need to disable stuff that can convert to the alternative from calling the std::function overload.
The easiest technique would be tag dispatching. Make an operator= that is greedy and set up for perfect forwarding, then manually dispatch to an assign method with a tag:
template<typename U>
void operator=(U&&u){
assign(std::forward<U>(u), std::is_convertible<U, std::wstring>());
}
void assign(std::wstring, std::true_type /*assign_to_string*/);
void assign(std::function<blah>, std::false_type /*assign_to_non_string*/);
basically we are doing manual overload resolution.
More advanced techniques: (probably not needed)
Another approach would be to limit the std::function = with SFINAE on the argument being invoked is valid, but that is messier.
If you have multiple different types competing with your std::function you have to sadly manually dispatch all of them. The way to fix that is to test if your type U is callable with nothing and the result convertible to T, then tag dispatch on that. Stick the non-std::function overloads in the alternative branch, and let usual more traditional overloading to occur for everything else.
There is a subtle difference in that a type convertible to both std::wstring and callable returning something convertible to T ends up being dispatched to different overloads than the original simple solution above, because the tests used are not actually mutually exclusive. For full manual emulation of C++ overloading (corrected for std::functions stupidity) you need to make that case ambiguous!
The last advanced thing to do would be to use auto and trailing return types to improve the ability of other code to detect if your = is valid. Personally, I would not do this before C++14 except under duress, unless I was writing some serious library code.
Both std::function and std::wstring have conversion operators that could take the literal wide string you are passing. In both cases the conversions are user defined and thus the conversion sequence takes the same precedence, causing the ambiguity. This is the root cause of the error.
Is there a non-boost way to create a function with variable arguments? I know the argument types number of arguments and they are usually less then 5, all of the same type.
I need to know if there is a way without supplying the argument count or ending the param list with null.
I know the argument types and they are usually less then 5.
If it is not going to be greater than 5, then simple overloads may do the work. Call the overload which accepts maximam number of arguments from all other overloads accepting less than 5 arguments, or define a worker (internal) function, call this from the overloads.
If possible, you could use default values for some of the parameters, if that helps reducing the number of overloaded functions.
In C++11, you could use variadic-template.
For up to 5 arguments all of the same type, simple overloads can do the trick.
For more generality, supporting any number of arguments of the same type, just pass a collection such as a std::vector.
For a C++03 technique to build such a collection on the fly in each call, see my other answer; for C++11, if you do not need to support Visual C++ you can use curly braces initializer lists as actual arguments.
Is cstdarg what you are looking for? This is the standard C++ way to generate functions with variable numbers of arguments.
You should be able achieve passing variable arguments using va_list.
You can:
if you're using C++11 you can use variadic templates, otherwise...
provide overloads
use arguments which default to some sentinel values you can recognise ala f(const T& v1 = missing, const T& v2 = missing, ...) { if (v5 != missing) ...
create a simple helper template that can optionally be constructed from the data type and has a bool to track whether it was
you may need to support types without default constructors by either using new/delete (simple and safe but slow) or having an aligned buffer you placement new into, manually destroy etc. (fiddly and easier to get wrong but faster)
some compilers have variadic macro support
if you're prepared to change the calling syntax a bit, you can use any number of things:
accept a vector (using a union or variant if the types differ)
accept an array (possibly using the template <size_t N> void f(T (&data)[N]) { ... } trick to have the compiler provide the array size to you automatically)
some kind of lhs object to which extra values can be supplied using an operator such as operator, or operator<<
As a general C++03 solution you can provide a setter that returns a reference to the object that it's called on, so that it can be called again. And again. And so on, called chaining.
It's the same scheme as iostreams use for operator<<.
E.g.
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
void foo( char const s[] )
{
cout << s << endl;
}
class StringBuilder
{
private:
string s_;
template< class Type >
string fastStringFrom( Type const& v )
{
stringstream stream;
stream << v;
return stream.str();
}
char const* fastStringFrom( char const* s )
{
return s;
}
string const& fastStringFrom( string const& s )
{
return s;
}
public:
template< class Type >
StringBuilder& operator<<( Type const& v )
{
s_ += fastStringFrom( v );
return *this; // Supports chaining.
}
operator string const& () const { return s_; }
operator char const* () const { return s_.c_str(); }
};
int main()
{
typedef StringBuilder S;
foo( S() << "6*7 = " << 6*7 << "." ); // Any number of arguments.
}
Instead of converting the argument values to text, you just do whatever it is that you need. For example, with a fixed set of possible types you can store the arguments in a collection.
If you do not need to support the Visual C++ compiler, then alternatively you can use a C++11 variadic template.
Suppose I have a class X:
class X {
// ...
size_t hash() const { return ...; }
};
I would like to create a std::tr1::unordered_map<X, int, HashFn> where I want to pass in
X::hash() as HashFn. I know I can declare my own functor object. I feel that
there should be a way to do this by directly passing a pointer to X::hash().
Is there?
No; as you've shown it, you need a small utility struct:
#include <functional>
template<typename T, std::size_t (T::*HashFunc)() const = &T::hash>
struct hasher : std::unary_function<T, std::size_t>
{
std::size_t operator ()(T const& t) const
{
return (t.*HashFunc)();
}
};
Then you can create an unordered_map like so:
std::tr1::unordered_map<X, int, hasher<X> > m;
No, there isn't. The reason is that whatever is used as your HashFn must take a single argument which is a const reference to an object in the container. X::hash takes a single argument which is a const pointer to an object in the container (the this pointer is an implicit first argument in this case), so using that function by it self is not possible.
You probably use some bind magic, using boost::lambda and boost::bind. I'm not exactly sure how, but it would probably look something like this:
boost::bind(&X::hash, &_1);
Which creates a function object which will call X::hash with a pointer.
size_t hash() const { return ...;}
A function which calculates hash value takes one parameter of type Key which your function doesn't take. Hence its signature is wrong to begin with.
Since you want to implement a function, rather than a functor, here is how it should be done:
size_t hash(const KeyType &key)
{
return /*calculate hash and return it*/;
}
Make it static member function and pass it as X::hash or make it a free function, is your choice.
You can't directly, but you can wrap it. The easy way to do so is to use boost::mem_fn(), or the standard equivalents if your compiler supports them: tr1::mem_fn() (from TR1) or std::mem_fn() (from C++11).
EDIT: Actually it's not so simple. mem_fn() will work fine for a function parameter, but since its return type is unspecified it's difficult to use as a template parameter. If you have C++11 support you could use decltype to find the type; otherwise you're probably best off writing your own function object as you mentioned.