C++ auto in static_cast - c++

The auto keyword can be used in many contexts and combined with other language elements, as in const auto& or auto&&. However, it cannot be used in cast operations. Consider the following example (which does not compile):
template <class T> void foo(T&& t) {}
int main() {
int i = 0;
foo(static_cast<const auto&>(i)); // This could call foo(const int&)
}
The cast would obviously work with int instead of auto, but being able to use auto in casts would be useful in generic code, for instance:
You could use const auto& (as above) to explicitly call an overloaded function with a const lvalue ref.
Similarly, you could use static_cast<auto&&> as a less verbose version of std::forward<decltype(x)>(x).
Thinking a bit further, static_cast<auto>(x) or something like auto(x) could be a way of explicitly copying an object.
(Note that explicit types instead of auto can be used in all these scenarios.)
To be honest, I intuitively expected this syntax to work (because it mirrors the way auto can be used in declarations), but to my mild surprise it didn't. Since it is such an obvious syntax, I am wondering whether there are specific reasons why it is disallowed? Or is it simply a case of nobody considering/proposing it as a feature?

Related

Is forwarding of all callables still not possible in C++20?

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.

Implement Clip() in Eigen

I have code that clips some value to be between a range centered around 0 like below.
Eigen::VectorXd a;
Eigen::VecotrXd b;
a = a.cwiseMin(b).cwiseMax(-b); // no temporary created here?
I want to factor out the logic into a function.
One solution:
Eigen::VectorXd Clip(const Eigen::VectorXd& a, const Eigen::VectorXd& b);
a = Clip(a, b);
But I assume this is inefficient as it creates an extra temporary?
Another solution:
void Clip(Eigen::Ref<Eigen::VectorXd> a, const Eigen::VectorXd& b) {
a = a.cwiseMin(b).cwiseMax(-b);
}
But this seems inconvenient to use sometimes:
void SomeFunctionSignatureICannotChange(const Eigen::VectorXd& a, const Eigen::VectorXd& b) {
// Eigen::VectorXd a_clipped = Clip(a, b); would be cleaner.
Eigen::VectorXd a_clipped;
Clip(a_clipped, b);
}
The best solution I can think of:
template <typename DerivedV, typename DerivedB>
auto Clip(const Eigen::ArrayBase<DerivedV>& v,
const Eigen::ArrayBase<DerivedB>& bound)
-> decltype(v.min(bound).max(-bound)) {
return v.min(bound).max(-bound);
}
(I assume 'auto' in this case is fine and not the one that common pitfalls warned against?)
However, the code seems template-heavy and a bit-complicated. For example, trailing return type is discouraged by google style guide here:
Use the new trailing-return-type form only in cases where it's
required (such as lambdas) or where, by putting the type after the
function's parameter list, it allows you to write the type in a much
more readable way. The latter case should be rare; it's mostly an
issue in fairly complicated template code, which is discouraged in
most cases.
Alternatively, if I remove the trailing return type, function return type deduction will kick in. But google style guide seems to also discourage function return type deduction in public headers here
Furthermore, use it only if the function or lambda has a very narrow
scope, because functions with deduced return types don't define
abstraction boundaries: the implementation is the interface. In
particular, public functions in header files should almost never have
deduced return types.
I'm new to Eigen and C++ so not sure if I missed anything. Hope to learn from everyone's comments and suggestions. Thanks!
I confirm that a = a.cwiseMin(b).cwiseMax(-b); does not create any temporary. In your case, using auto return type is highly recommended, and I would also argue that your use case is a perfectly legit exception to the aforementioned rules:
Writing the return type explicitly would be a nightmare and error prone.
This is a very short function that is expected to be inlined. It is thus expected to be declared and defined at the same time. Therefore the second rule does not not really apply.
In c++14 you can even omit the redundancy:
template <typename DerivedV, typename DerivedB>
auto Clip(const Eigen::ArrayBase<DerivedV>& v,
const Eigen::ArrayBase<DerivedB>& bound)
{
return v.min(bound).max(-bound);
}

Does C++/11 auto keyword deduce to parameters to pass-by-reference when that is more efficient, or always pass-by-value?

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.

spawn a copy as input to function taking rvalue reference

I have a library function (not under my control here) which take an r value reference to the movable and copyable type Bar:
void foo(Bar&& b);
In my own code, I sometimes need to give it a copy of an existing value, such as
const auto b = getBar();
foo(mk_copy(b));
b.baz();
This is what comes to mind,
template<typename T> auto mk_copy(T val){return val;}
Is there a standard way to do this, or a more common pattern? Perhaps even
template<typename T> auto mk_copy(T&& val){return std::forward<T>(val);}
Or, as pscill points out just writing the name of the class again,
foo(Bar(b));
but I prefer not to repeat type names.
For the built-in types the prefix + plays the role of “make a copy”:
void foo( char&& ) {}
void bar( double*&& ) {}
auto main() -> int
{
char x{};
foo( +x );
double* p{};
bar( +p );
}
Still, it would probably be confusing to readers of the code if you applied prefix + to some other type, and a general prefix operator+ template might end up in conflict with some class' own prefix operator+.
So, I suggest using the now apparent naming convention for makers, namely a make prefix.
Then it can look like this:
template< class Type >
auto make_copy( Type const& o ) -> Type { return o; }
Your first proposed solution,
template<typename T> auto mk_copy(T val){return val;}
suffers from potentially copying the value twice: first copying to the by-value argument, and then copying to the function result.
This is not a problem for a movable type such as a standard library container, because the return type copying will reduce to a move. But it can be a problem for largish non-movable type, as can occur in legacy code.
The second proposed solution,
template<typename T> auto mk_copy(T&& val){return std::forward<T>(val);}
takes the argument by forwarding reference (a.k.a. universal reference), and then deduces the return type from a re-creation of the argument type. The return type will always be a non-reference, since that's what plain auto deduces, so this is technically correct. But it's needlessly complicated.
There is no standard mechanism, but if you want one, your examples aren't very good. The first mk_copy copies T twice (or copies and moves). The second one seems very confusing as to what it's trying to do.
The obvious way is to simply take a const T&, like you normally would:
template<typename T> T mk_copy(const T &val){return val;}
I think you'd better just define that mk_copy method, or add one more declaration:
auto b_copy = b;
foo(std::move(b_copy));
These are clearer to the readers.
Just to demonstrate the possibilities, you could use decltype to get the type:
foo(std::decay_t<decltype(b)>{b});
or you could get the same effect with lambdas:
foo([&]{return b;}());
or tuples:
foo(std::get<0>(std::make_tuple(b)));
or pairs:
foo(std::make_pair(b, 0).first);

Does implicit T& constructor of std::reference_wrapper<T> make it dangerous to use?

boost::reference_wrapper<T> has an explicit T& constructor, while std::reference_wrapper<T> has an implicit one. So, in the following code:
foo = bar;
If foo is a boost::reference_wrapper, the code will fail to compile (which is good, since reference_wrapper does not have the same semantics of an actual reference.
If foo is a std::reference_wrapper, the code will "rebind" foo's reference to bar (instead of assigning the value as one might mistakenly expect it to).
This could result in elusive bugs... Consider the following example:
In version 1.0 of some hypothetical library:
void set_max(int& i, int a, int b) {
i = (a > b) ? a : b;
}
In a new version (1.1), set_max is converted to a template to accept integers of any width (or UDT's) without changing the interface:
template<typename T1, typename T2, typename T3>
void set_max(T1& i, T2 a, T3 b) {
i = (a > b) ? a : b;
}
Then finally, in some application using the library:
// i is a std::reference_wrapper<int> passed to this template function or class
set_max(i, 7, 11);
In this example, the library changes its implementation of set_max without changing the call interface. This would silently break any code that passes it a std::reference_wrapper as the argument would no longer convert to int& and would instead "rebind" to a dangling reference (a or b).
My question: Why did the standards committee elect to allow implicit conversion (from T& to std::reference_wrapper<T>) instead of following boost and making the T& constructor explicit?
Edit: (in response to the answer offered by Jonathan Wakely)...
The original demo (in the section above) is intentionally concise to show how a subtle library change could result in the use of std::reference_wrapper introducing bugs to an application.
The next demo is provided to show a real-world, legitimate use of reference_wrapper for "passing references through interfaces", in response to Jonathan Wakely's point.
From Developer/Vendor A
Something similar to std::bind but pretend it's specialized for some task:
template<typename FuncType, typename ArgType>
struct MyDeferredFunctionCall
{
MyDeferredFunctionCall(FuncType _f, ArgType _a) : f(_f), a(_a) {}
template<typename T>
void operator()(T t) { f(a, t); }
FuncType f;
ArgType a;
};
From Developer/Vendor B
A RunningMax functor class. Between version 1.0 and 1.1 of this imaginary library, the implementation of RunningMax was changed to be more generic, without changing its call interface. For purposes of this demo, the old implementation is defined in namespace lib_v1, while the new implementation in defined in lib_v2:
namespace lib_v1 {
struct RunningMax {
void operator()(int& curMax, int newVal) {
if ( newVal > curMax ) { curMax = newVal; }
}
};
}
namespace lib_v2 {
struct RunningMax {
template<typename T1, typename T2>
void operator()(T1& curMax, T2 newVal) {
if ( newVal > curMax ) { curMax = newVal; }
}
};
}
And last but not least, the end-user of all the above code:
Some developer using the code from Vendor/Developer A and B to accomplish some task:
int main() {
int _i = 7;
auto i = std::ref(_i);
auto f = lib_v2::RunningMax{};
using MyDFC = MyDeferredFunctionCall<decltype(f), decltype(i)>;
MyDFC dfc = MyDFC(f, i);
dfc(11);
std::cout << "i=[" << _i << "]" << std::endl; // should be 11
}
Note the following:
The end-user uses std::reference_wrapper the way in which it's intended.
Individually, none of the code has bugs or logical flaws, and everything worked perfectly with the original version of Vendor B's library.
boost::reference_wrapper would fail to compile upon upgrading the library, while std::reference_wrapper silently introduces a bug that may or may not be caught in regression tests.
Tracing such a bug would be difficult, since the "rebinding" is not a memory-error that tools such as valgrind would catch. Furthermore, the actual site of the misuse of std::reference_wrapper would be within Vendor B's library code, not the end-user's.
The bottom line: boost::reference_wrapper seems safer by declaring its T& constructor as explicit, and would prevent the introduction of a bug such as this. The decision to remove explicit constructor restriction in std::reference_wrapper seems like it compromised safety for convenience, something that should rarely occur in language/library design.
This would silently break any code that passes it a std::reference_wrapper as the argument would no longer convert to int& and would instead "rebind" to a dangling reference (a or b).
So don't do that.
reference_wrapper is for passing references through interfaces that would otherwise make a by-value copy, it's not for passing to arbitrary code.
Also:
// i is a std::reference_wrapper<int> (perhaps b/c std::decay wasn't used)
decay wouldn't change anything, it doesn't affect reference wrappers.
The reason implicit conversion (T& --> reference_wrapper<T>) is allowed for std::reference_wrapper<T>, but not boost::reference_wrapper<T>, is sufficiently explained in the DR-689 link provided by Nate Kohl. To summarize:
In 2007, the C++0x/C++11 Library Working Group (LWG) proposed change #DR-689 to section 20.8.3.1 [refwrap.const] of the standard:
The constructor of reference_wrapper is currently explicit.
The primary motivation behind this is the safety problem with respect
to rvalues, which is addressed by the proposed resolution of [DR-688].
Therefore we should consider relaxing the requirements
on the constructor since requests for the implicit conversion keep
resurfacing.
Proposed resolution: Remove explicit from the constructor of reference_wrapper.
It's worth pointing out:
boost::reference_wrapper has not been relaxed in such a way, nor does there appear to be a proposal for it, which creates an inconsistency between the semantics of boost::reference_wrapper and std::reference_wrapper.
Based on the verbiage in DR-689 (specifically the "requests keep surfacing" part) it seems likely that this change was simply viewed by the LWG as an acceptable tradeoff between safety and convenience (in contrast to its boost counterpart).
It's unclear whether the LWG anticipated other potential risks (such as those demonstrated in the examples provided on this page), since the only risk mentioned in DR-689 was that of binding to an rvalue (as described and resolved in the previous entry, DR-688).