resolve address from overloaded function std::real<float> - c++

std::vector<std::complex<float> > c;
std::vector<float> d;
std::transform(c.begin(), c.end(), d.begin(), std::real<float>);
Why couldn't the compiler resolve the address from the overloaded function real<float>?
Which overloaded functions does the compiler mean?

Your library implementation has provided additional overloads for std::real<float>.
Why the overloads?
26.4.9 Additional overloads [cmplx.over]
1 The following function templates shall have additional overloads:
arg norm
conj proj
imag real
2 The additional overloads shall be sufficient to ensure:
If the argument has type long double, then it is effectively cast to complex<long double>.
Otherwise, if the argument has type double or an integer type, then it is effectively cast to complex<double>.
Otherwise, if the argument has type float, then it is effectively cast to complex<float>.
[...]
Solutions to problem:
You could just use a range based for ...
for (auto v : c) d.push_back(real(v));
... or pack the call to real into a functor or another function ...
struct my_caller {
template <typename T> T operator() (std::complex<T> const &c) {
return real(c);
}
};
... or use the member function ...
std::transform(c.begin(), c.end(), d.begin(), [](std::complex<T> const &c) {
return c.real();
});
IMPORTANT:
Note that you have to have enough space in the target when using transform:
std::vector<float> d (c.size());
or use a back inserter:
std::transform(c.begin(), c.end(), back_inserter(d), ...);
Otherwise you are iterating over undefined memory, yielding undefined behaviour.

§26.4.9 states that (amongst others), real shall have additional overloads, for arguments of type float, double and long double. It seems your libraray implementation made a template for these overloads, maybe like
template <typename T>
T real(T const& t)
{
return std::real(std::complex<T>{t});
}
In addition to the solutions phresnel priovided, you could explicitly tell the compiler which kind of function pointer you mean:
std::transform(c.begin(), c.end(), d.begin(), (float(*)(std::complex<float> const&))std::real<float>);
The compiler then looks for a std::real that can be converted into a function pointer of the given type and will find the correct one.
I tell you this only for completeness - I consider this explicit cast ugly and would prefer the ranged based for or transform with a lambda.

Related

Casting to void to avoid use of overloaded user-defined Comma operator

I am learning about templates in C++, and came across an example where casting to void is used:
template<typename T>
auto func (T const& t) -> decltype( (void)(t.size()), T::size_type() )
{
return t.size();
}
In the explanation it is written that:
The cast of the expression to void is to avoid the possibility of a user-defined comma operator overloaded for the type of the expressions.
My question(s) is/are:
How can a cast to void be used to "avoid the possibility of a user-defined comma operator overloaded for the type of the expressions"? I mean, can anyone give any example where if we don't use void then this code would give an error? For example, let's say we have a class called SomeClass which has overloaded the comma operator. Now, can this become a problem if we don't use void?
Can static_cast be used in this case instead of a C style cast? For example, something like static_cast<void>(t.size()). I am reading examples that use C++17 features, and so I wonder why the author has used a C style cast in this case.
I have read What does casting to `void` really do?, from which I get the impression that if we use (void)x then this means to suppress compiler warnings, and also means "ignore the value of x". But then I can't understand the difference between the expression x and (void)x.
Consider this pathological type:
struct foo {
struct size_type {
bool operator,(size_type) { return false;}
};
size_type size() { return {};}
};
It does have a size_type and it does have a size() method. However, without the cast to void, the template does not deduce the right return type, because decltype( (t.size()), typename T::size_type() ) is bool :
#include <type_traits>
template<typename T>
auto func (T const& t) -> decltype( (t.size()), typename T::size_type() )
{
return t.size();
}
struct foo {
struct size_type {
bool operator,(size_type) { return false;}
};
size_type size() const { return {};}
};
int main()
{
func(foo{});
}
Results in error:
<source>:6:8: error: no viable conversion from returned value of type 'foo::size_type' to function return type 'decltype((t.size()) , typename foo::size_type())' (aka 'bool')
return t.size();
^~~~~~~~
<source>:20:4: note: in instantiation of function template specialization 'func<foo>' requested here
func(foo{});
^
1 error generated.
ASM generation compiler returned: 1
<source>:6:8: error: no viable conversion from returned value of type 'foo::size_type' to function return type 'decltype((t.size()) , typename foo::size_type())' (aka 'bool')
return t.size();
^~~~~~~~
<source>:20:4: note: in instantiation of function template specialization 'func<foo>' requested here
func(foo{});
^
A static_cast can be used. However, as nothing is actually being cast (it is an unevaluated context), the c-style cast does not do much harm. Note how by using the cast to void the user defined operator, is bypassed and the correct return type is deduced: https://godbolt.org/z/jozx1YGWr. This is because void, whatever uses the built-in operator, whose result is of same type as whatever. You cannot override void, whatever with a user-defined operator,; there is no syntax that works.
I suppose the code is merely to illustrate this one effect, because even with the cast to void one can make up other examples that fail (eg the template does not explicitly test for t.size() actually returning T::size_type).
See also the section on "Rarely overloaded operators" here:
The comma operator, operator,. Unlike the built-in version, the overloads do not sequence their left operand before the right one. (until C++17) Because this operator may be overloaded, generic libraries use expressions such as a,void(),b instead of a,b to sequence execution of expressions of user-defined types. The boost library uses operator, in boost.assign, boost.spirit, and other libraries. The database access library SOCI also overloads operator,.

Why could not deduce template argument when passing lambda instead of function pointer

I have a bubble-sort function that takes an array, a compare function, and a boolean that indicates if it should sorts the array upside-down. It is a template function that supports any data-type, and will deduce array size automatically.
When specifying the compare function, if I pass function pointer, the compiler will deduce the data type of array automatically, which is great. But if I pass a lambda instead, it will not deduce automatically. I have to specify the data type explicitly, or static_cast the lambda as fnCompare_t<double>.
What is the reason behind this? Because according to this post, as long as the lambda doesn't capture, it can be used like the plain-old function pointer, but it seems it is not always the case? How come it can be different in this case?
#include <iostream>
using namespace std;
template <typename T>
using fnCompare_t = int(*)(T const &, T const &);
template <typename T, size_t count>
inline void BubbleSort(
T(&array)[count],
fnCompare_t<T> fnCompare,
bool reverse)
{
cout << "TODO: Implement BubbleSort" << endl;
}
double doubleArray[] = {
22.3, 11.2, 33.21, 44.2, 91.2, 15.2, 77.1, 8.2
};
int CompareDouble(double const & a, double const & b)
{
return a > b ? 1 : a == b ? 0 : -1;
}
int main()
{
auto fnCompare = [](double const & a, double const & b) -> int {
return a > b ? 1 : a < b ? -1 : 0;
};
// compile OK:
BubbleSort(doubleArray, CompareDouble, false);
BubbleSort(doubleArray, static_cast<fnCompare_t<double>>(fnCompare), false);
BubbleSort<double>(doubleArray, fnCompare, false);
// compile error, could not deduce template argument:
//BubbleSort(doubleArray, fnCompare, false);
return 0;
}
The reason why is because you can't get an implicit conversion on a templated parameter when using deduction. The classic example is:
template <class T>
T min(T x, T y);
Calling this function as min(1, 3.0) will result in a failure. Because for both arguments, it tries to find a T to get a perfect match, and fails. If you specify the template parameter explicitly it can work: min<double>(1, 3.0). The same is true in your example, if you specify T explicitly it will work.
The idiomatic way to write the signature for your function is:
template <typename Iter, typename F>
inline void BubbleSort(
Iter b, Iter e,
F fnCompare,
bool reverse)
However, this discards the compile time length information. If you want to keep that, you can do:
template <typename T, size_t count, typename F>
inline void BubbleSort(
T(&array)[count],
F fnCompare,
bool reverse);
Though you should at least consider using std::array instead of a C style array which will make the signature a bit less ugly and has other benefits.
This may seem odd as we are not "verifying" the comparator having the correct signature, in the signature of our sort. But this is normal in C++, if the comparator is incorrect then it will fail at the point of usage and it will still be a compile time error. Note as well when you try to depend on a lambda implicitly converting into a function pointer, you are being unnecessarily restrictive: lambdas only convert into function pointers with identical signature. Even if the output of the lambda is implicitly convertible to the output of the function pointer, your lambda will not implicitly convert, even though the lambda can still be used!
As a final final note, it's usually better to pass functors because it's better for performance. Comparators are usually small functions and often will get inlined. But in your version, the comparator will not typically be inlined, in mine it will (because I preserve the original type of the lambda, and you do not).
You need to explicitly cast the lambda to a function pointer. There is no other way around it. But, instead of static_casting you can apply + to the lambda, which would trigger the function pointer conversion, as you can apply + to a pointer type:
BubbleSort(doubleArray, +fnCompare, false);
// ^^
// applying unary + invokes the function pointer conversion operator
The reason for why there is no implicit call to the conversion operator is that during overload resolution, the compiler will only consider templates that match perfectly (see this for more info). Because a lambda is not a function pointer, there cannot be a perfect match, and the overload is discarded.

How does overloading function call work in C++?

I read that function call () can also be overloaded. http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B
What would the following mean?
It works.
template<typename T, typename Comp>
struct bind{
T v;
Comp comp;
bool operator()(const T& b){
return comp(b,v);
}
};
int main(){
bind<int, less<int> > b;
b.v = 2;
cout << b(3) << "\n";
}
It means that if you create an object of type bind<>, you can apply the function-call operator to that object.
Like this:
bind<int, std::less<int>> b;
b.v = 2;
std::cout << b(1) << "\n";
That snippet might print "true" on the standard output.
If you have a class called foo, I'm sure you understand what it means to call a member function of an object of that type:
foo f;
f.bar();
You may also understand that you can overload certain operations. For example, you could overload operator+ for foo so that you could do something like this:
foo f, g;
f + g;
Now you can also overload operator() for a class, which allows you to call it as though it were a function:
foo f;
f();
Yes, f is not a function but it is an object of class type that overloads operator(). Class types that do this are known as functors or function objects.
In the example you've given, bind is a functor. When you create an object of that type, you can call it like a function, passing it a const T& and it will return a bool back to you. The implementation of operator() actually calls the function stored in comp, passing it both the T object you passed to operator(), a, and the member object v of type T.
As it stands, it doesn't mean much of anything except "syntax error". For example:
template<T, Op>
This simply isn't allowed. For each template parameter, you need to specify whether it's a type (using class or typename) or a non-type parameter such as an int. Since the apparent intent is that both these should be type parameters, you need something like:
template <class T, class Op>
or:
template <typename T, typename Op>
For this situation, there's no difference in meaning between class and typename.
struct bind{
T v;
Leaving v uninitialized will lead to undefined behavior, so you probably don't want to allow that. You'd normally prevent it by adding a constructor that takes a T as its parameter and initializes v to that value:
bind(T const &v) : v(v) {}
When you include a constructor like this, the compiler won't automatically generate a default constructor, so it's no longer possible to create a bind object with v uninitialized -- exactly what we wanted.
Although creating the comp object:
Op comp;
is fairly harmless, it's also quite unnecessary. You could just as well do the comparison with a temporary instance created with Op(), in which case this:
bool operator()(const T& a){
return comp(a,v);
}
...would become something like this (and the Op comp; simply removed):
bool operator()(T const &a) {
return Op()(a, v);
}
Even with the corrections, I'd consider this code obsolescent. In C++98/03, it would have been useful in a situation where you needed to supply a functor to an algorithm, such as:
std::remove_copy_if(a.begin(), a.end(), bind<int,
std::back_inserter(b),
bind<int, std::less<int> >(5));
...which would copy numbers from a to b, removing those less that 5.
In C++11, however, most (if not all) uses of this bind should probably be written as lambdas instead though, so the bit above would become something like:
std::remove_copy_if(a.begin(), a.end(), bind<int,
std::back_inserter(b),
[](int x) { return x < 5; });
This is not only shorter, but (at least once you're used to it) quite a bit simpler than using std::less and bind to put together a function. It won't generally make any difference in run-time efficiency -- a lambda is basically a "shorthand" way of generating a class template, so what it generates would end up pretty similar to the code using bind.

C++11 - std::function, templates and function objects, weird issues

I'm playing with some code and I am a little puzzled about some stuff. Here's a simplified example:
I have Nodes that perform arithmetical operations (addition, subtraction, etc). I have a container with the different operations that are available in my program. Here's an example:
typedef std::binary_function<double, std::vector<double>&, std::vector<Node*>& > my_binary_function;
auto const & product = [](double v, Node* n){ return v * n->GetEvaluation(); };
struct addition : public my_binary_function {
double
operator()(std::vector<double>& weights, std::vector<Node*>& subtrees) {
return std::inner_product(weights.begin(), weights.end(),
subtrees.begin(), 0, std::plus<double>(), product);
}
};
Now, at this point there are two choices:
1) use a function type:
typedef double (*my_function)(std::vector<double>&, std::vector<Node*>&);
Then use the following templated function to convert the functors:
template<typename F> typename F::result_type
func(typename F::first_argument_type arg1, typename F::second_argument_type arg2) {
return F()(arg1, arg2);
}
2) use a function wrapper type, namely std::function, so that I have
typedef std::function<double (std::vector<double>&, std::vector<Node*>&)> my_function;
It all boils down to something like this:
LoadDefaultFunctions() {
int minArity = 2;
int maxArity = 2;
function_set_.AddFunction("Add", func<addition> , minArity, maxArity, 1.0); // case 1
OR
function_set_.AddFunction("Add", addition(), minArity, maxArity, 1.0); // case 2
And now the problems:
a) If I use Method 1, I get this compilation error:
error: invalid initialization of non-const reference of type
'std::binary_function<double, std::vector<double>&,
std::vector<Node*>&>::result_type {aka std::vector<Node*>&}'
from an rvalue of type 'double'
The error goes away if I change the template (notice how the arguments don't really make sense now):
template <typename F> typename F::first_argument_type
func1(typename F::second_argument_type arg1, typename F::result_type arg2) {
return F()(arg1, arg2);
}
I find it very strange, because for other types such as binary_op<double, double, double>, the first form works fine. So, what's happening?
b) 1) is faster than 2) (by a small margin). I'm thinking I'm probably missing some neat trick of passing the functor by reference or in some way that would enable std::function to wrap it more efficiently. Any ideas?
c) If I use the typedef from 2) but additionally I still use func to produce a function out of the functor, and let std::function deal with it, it's still faster than 2). That is:
`my_function = func<addition>` is faster than `my_function = addition()`
I would really appreciate it if someone could help me understand the mechanics behind all of this.
Thanks.
b) 1) is faster than 2) (by a small margin). I'm thinking I'm probably missing some neat trick of passing the functor by reference or in some way that would enable std::function to wrap it more efficiently. Any ideas?
Yes, I would expect 1 to be faster than 2. std::function performs type-erasure (the exact type of the stored callable is not present in the enclosing std::function type) which requires the use of a virtual function call. On the other hand, when you use a template, the exact type is known, and the compiler has greater chances of inlining the calls, making it a no-cost solution. This is not related to how you pass the functor.
The error
The order of the template arguments is incorrect:
typedef std::binary_function<double, // arg1
std::vector<double>&, // arg2
std::vector<Node*>& // return type
> my_binary_function;
struct addition : public my_binary_function {
double // return type
operator()( std::vector<double>& weights, // arg1
std::vector<Node*>& subtrees) // arg2
{ ...
That is, inheritance from binary_function is adding some typedefs to your class, but those are not the correct typedefs. Then when you use the typedefs in the next template, the types don't match. The template is expecting that your operator() will return a std::vector<Node*>&, and that is the return type of func, but when you call the functor what you get is a double which leads to the error:
invalid initialization of ... std::vector<Node*>& from double

Deducing knowledge of original types, whilst simultaneously forwarding

Summary: I want to end up with a function that deduces the exact types it was called with and takes (e.g.) a tuple that forwards them (the types of which will be different from the exact types the function was called with).
I'm stuck trying to "know" via deduction the types of the arguments to a given function, whilst simultaneously forwarding them. I think I might be missing something crucial about how this works.
#include <tuple>
#include <string>
#include <functional>
template <typename ...Args>
struct unresolved_linker_to_print_the_type {
unresolved_linker_to_print_the_type();
};
void f(int,double,void*,std::string&,const char*) {
}
template <typename F, typename ...Args>
void g1(F func, Args&&... args) {
unresolved_linker_to_print_the_type<Args...>();
auto tuple = std::forward_as_tuple(args...);
unresolved_linker_to_print_the_type<decltype(tuple)>();
}
template <typename F, typename T, typename ...Args>
void g2(F func, const T& tuple, Args... args) {
unresolved_linker_to_print_the_type<Args...>();
unresolved_linker_to_print_the_type<decltype(tuple)>();
}
int main() {
int i;
double d;
void *ptr;
std::string str;
std::string& sref = str;
const char *cstr = "HI";
g1(f, i,d,ptr,sref,cstr);
g2(f, std::forward_as_tuple(i,d,ptr,sref,cstr), i,d,ptr,sref,cstr);
}
What I'd like to see is a scenario where when my function (e.g. g1 or g2) gets called it knows and can use both the original types - int,double,void*,std::string&,const char* and the forwarded arugments too.
In this instance I don't seem to be able to find this information from within g1 or g2. The (deliberate, to print out the types) linker error shows me in g1 they are:
int&, double&, void*&, std::string&, char const*&
int&, double&, void*&, std::string&, char const*&
and in g2:
int, double, void*, std::string, char const*
int&, double&, void*&, std::string&, char const*&
There are two thing I don't get here:
Why do none of the printed (via the linker error) types match what I actually passed in? (int,double,void*,std::string&,const char). Can I deduce what I actually was passed? Preferably with "natural" syntax, i.e. everything just once and nothing explicitly written out. I can explicitly write:
g2<decltype(&f),decltype(std::forward_as_tuple(i,d,ptr,sref,cstr)),int,double,void*,std::string&,const char*>(f,std::forward_as_tuple(i,d,ptr,sref,cstr),i,d,ptr,sref,cstr);
but that's "unwieldy" to say the least!
In g1 the presence of && in the function signature declaration seems to alter the types in the template parameter Args itself. Compare that with:
template <typename T>
void test(T t);
Or:
template <typename T>
void test(T& t);
using either of those with:
int i;
test(i);
doesn't change the type of T. Why does the && change the type of T itself when & doesn't?
Answer to first question:
Arguments to functions are expressions, not types. The difference between these two is expressed in chapter 5 [expr], p5:
If an expression initially has the type “reference to T” (8.3.2,
8.5.3), the type is adjusted to T prior to any further analysis.
Thus, there is no difference what-so-ever between g(str) and g(sref). g() always sees a std::string, and never a reference.
Additionally expressions can be lvalue or rvalue (actually that's a simplification of the C++11 rules, but it is close enough for this discussion - if you want the details they're in 3.10 [basic.lval]).
Answer to second question:
Template parameters of the form:
template <class T>
void g(T&&);
are special. They are unlike T, T&, or even const T&& in the following way:
When T&& binds to an lvalue, T is deduced as an lvalue reference type, otherwise T deduces exactly as per the normal deduction rules.
Examples:
int i = 0;
g(i); // calls g<int&>(i)
g(0); // calls g<int>(0)
This behavior is to support so called perfect forwarding which typically looks like:
struct A{};
void bar(const A&);
void bar(A&&);
template <class T>
void foo(T&& t)
{
bar(static_cast<T&&>(t)); // real code would use std::forward<T> here
}
If one calls foo(A()) (an rvalue A), T deduces per normal rules as A. Inside of foo we cast t to an A&& (an rvalue) and call bar. The overload of bar that takes an rvalue A is then chosen. I.e. if we call foo with an rvalue, then foo calls bar with an rvalue.
But if we call foo(a) (an lvalue A), then T deduces as A&. Now the cast looks like:
static_cast<A& &&>(t);
which under the reference collapsing rules simplifies to:
static_cast<A&>(t);
I.e. the lvalue t is cast to an lvalue (a no-op cast), and thus the bar overload taking an lvalue is called. I.e. if we call foo with an lvalue, then foo calls bar with an lvalue. And that's where the term perfect forwarding comes from.
types (even in C++) are mostly a compile type notion (except of course the RTTI in vtables).
If you need entirely dynamic types, then C++ might not be the best language for that.
You might perhaps extend GCC (actually g++, assuming it is at least 4.6) with a plugin or a GCC MELT extension (MELT is a high level domain specific language to extend GCC) which does what you want (e.g. for instance providing an additional builtin which encode the type of its arguments in some constant string, etc...), but that does require some work (and is specific to GCC).
But I don't understand why you want to do such baroque things in C. If dynamic typing is so important to you, why don't you use a dynamically typed language??