C++ Auto Keyword - Float vs Int Trouble - c++

I'm relatively new to C++. I just read about the auto keyword in regards to type deduction. I've tried implementing this in a couple functions only to find that it was causing all of kinds of issues when working with math operators. I believe what was happening was that my functions started implementing integer division when I actually needed float division (variables 'i' and 'avg'). I posted the code using the auto keywords below.
Now when I explicitly declared the variables as floats, the function worked fine.
So is this an example in which using auto would not be preferred? However, I can definitely see that they would help when generating the iterators.
namespace Probability
{
/* ExpectedValueDataSet - Calculates the expected value of a data set */
template <typename T, std::size_t N>
double ExpectedValueDataSet(const std::array<T, N>& data)
{
auto i = 0;
auto avg = 0;
for(auto it = data.begin(); it != data.end(); it++)
{
i = it - data.begin() + 1;
avg = ((i-1)/i)*avg + (*it)/i;
}
std::cout << avg << " \n";
return avg;
}
};

The literal 0 is of type int.
A variable auto avg = 0; therefore has type int.
The literal 0.0 (or e.g. 3.14) has type double, which is what you want.
As a general rule, use auto for a variable declaration where
the type is explicitly specified in the initializer, or
the type is awfully verbose, like some iterator type.
But don't use it without reason. :)
If for e.g. aesthetic reasons you want to keep i as an integer, then rewrite the computation
((i-1)/i)*avg + (*it)/i
to e.g.
((i-1)*avg + *it)/i
to avoid pure integer arithmetic for (i-1)/i.

Related

How to explicitly cast argument to match an expected function parameter?

I am trying to write a generic function to compute an average over a certain range.
template <typename Range, typename Ret, typename Func>
Ret average(Range range, Ret zero, Func extract) {
Ret sum = zero;
int numElements = 0;
for (const auto& elem : range) {
sum += extract(elem);
++numElements;
}
if (numElements > 0)
sum /= numElements;
return sum;
}
The problam I am having is with the usage of the /= operator, but to better clarify the arguments of this function, let me clarify them:
Range range is any object that defines a range through begin() and end() member funcitons. I may need to add const& to avoid unnecessary copying.
Ret zero defines the neutral element of the addition used when computing the average. It could be just a scalar, but will work with vectors or matrices too for example.
Func extract is a function (usually given as a lambda function) that converts the elements of the range into Ret values that I average over. In practice I use it as a getter of a specific field in big objects that I iterate over.
I could probably define it as std::function<Ret(decltype(*range.begin()))> or something similar, if C++ didn't have problems deducting types this way.
I assume that Ret provides some /= operator that the above function can work with, but I do not want to require it to take an int specifically.
In my use case, for example, Ret works with float-s and this gives me an annoying warning:
warning: 'argument': conversion from 'int' to 'float', possible loss of data
So, what are my options to make the above function clean and work with any suitable operator/=?
I tried, for example, to deduct the type of the right argument of the operator and explicitly cast to it:
template <typename Range, typename Ret, typename Func>
Ret average(Range range, Ret zero, Func extract) {
Ret sum = zero;
int numElements = 0;
for (const auto& elem : range) {
sum += extract(elem);
++numElements;
}
using F = std::remove_pointer<decltype(&Ret::operator/=)>;
if (numElements > 0)
sum /= static_cast<typename boost::function_traits<F>::arg1_type>(numElements);
return sum;
}
But I get a lot of compile errors, suggesting that I don't know what I am doing. Starts with:
error: 'boost::detail::function_traits_helper<std::remove_pointer<SpecificTypeUsedAsRet &(__cdecl SpecificTypeUsedAsRet::* )(float)> *>': base class undefined
That's probably because boost::function_traits does not work with member functions, just regular ones?
I am also concerned that this solution may not work when:
The operator/= is not given as a member function, but as a regular function with two arguments.
The operator/= is overloaded with respect to its right operand. An int may match only one of the overloads - so there is no ambiguity, but decltype won't know which overload to take.
I would prefer not to use boost but stick to the powers provided by newest C++ standards
You could simply declare Ret numElements = 0; instead of making it an int. If it has /= operator, it probably has an ++ operator; or you could use num_elements += 1 instead.

Why type deduction for auto specifier cares about only init field of the for-loop?

The following example seems to be very easy and straightforward:
void ftest(size_t& arg)
{
std::cout << arg << '\n';
}
int main()
{
size_t max = 5;
for (auto i = 0; i < max; ++i)
ftest(i);
}
but it won't compile (at least using VS2013) because the i is deduced as int and not as size_t. And the question is -- what is the point of auto in such for-loops if it can't rely on the conditional field? Would it be too much hard and time consuming if a compile analyze the whole statement and give expected result instead of what we're having now?
Because the type of variable is determined when declared (from its initializer), it has nothing do with how it will be used. If necessary type conversion would be considered. The rule is same as variables declared with type specified explicitly, auto is just helping you to deduce the type, it's not special.
Try to consider about this:
auto max = 5u;
for (auto i = 0; i < max; ++i)
// ~~~~~~~~
// i should be unsigned int, or max should be int ?
BTW: You could use decltype if you want the type to be determined by the conditional field max:
for (decltype(max) i = 0; i < max; ++i)
Keyword auto has nothing do with the rest of for statement, neither it knows about it. If you say it should infer from max, you are saying delay the type deduction, which won't comply with the auto type-inference rules.
Additionally, what about this?
size_t max = 5;
short min = 1;
for (auto i = 0; i < max && i > min; ++i)
Should it infer to short or size_t ? You cannot make compiler to read your mind!
Also, such delayed inference rules (if any) would complicate templates meta-programming.
You are actually providing a very simple case, where the condition is a simple i < max where the type of max is known. The standard tries to provide rules that apply in all cases, now let's consider this:
bool f(int);
bool f(size_t);
for (auto i = 0; f(i); ++i) { }
If the type of i was dependent on the conditional expression in the for loop, your compiler will probably not be happy.
Also, Herb Sutter as a small post on its blog about this issue actually: https://herbsutter.com/2015/01/14/reader-qa-auto-and-for-loop-index-variables/

Why isn't a for-loop a compile-time expression?

If I want to do something like iterate over a tuple, I have to resort to crazy template metaprogramming and template helper specializations. For example, the following program won't work:
#include <iostream>
#include <tuple>
#include <utility>
constexpr auto multiple_return_values()
{
return std::make_tuple(3, 3.14, "pi");
}
template <typename T>
constexpr void foo(T t)
{
for (auto i = 0u; i < std::tuple_size<T>::value; ++i)
{
std::get<i>(t);
}
}
int main()
{
constexpr auto ret = multiple_return_values();
foo(ret);
}
Because i can't be const or we wouldn't be able to implement it. But for loops are a compile-time construct that can be evaluated statically. Compilers are free to remove it, transform it, fold it, unroll it or do whatever they want with it thanks to the as-if rule. But then why can't loops be used in a constexpr manner? There's nothing in this code that needs to be done at "runtime". Compiler optimizations are proof of that.
I know that you could potentially modify i inside the body of the loop, but the compiler can still be able to detect that. Example:
// ...snip...
template <typename T>
constexpr int foo(T t)
{
/* Dead code */
for (auto i = 0u; i < std::tuple_size<T>::value; ++i)
{
}
return 42;
}
int main()
{
constexpr auto ret = multiple_return_values();
/* No error */
std::array<int, foo(ret)> arr;
}
Since std::get<>() is a compile-time construct, unlike std::cout.operator<<, I can't see why it's disallowed.
πάντα ῥεῖ gave a good and useful answer, I would like to mention another issue though with constexpr for.
In C++, at the most fundamental level, all expressions have a type which can be determined statically (at compile-time). There are things like RTTI and boost::any of course, but they are built on top of this framework, and the static type of an expression is an important concept for understanding some of the rules in the standard.
Suppose that you can iterate over a heterogenous container using a fancy for syntax, like this maybe:
std::tuple<int, float, std::string> my_tuple;
for (const auto & x : my_tuple) {
f(x);
}
Here, f is some overloaded function. Clearly, the intended meaning of this is to call different overloads of f for each of the types in the tuple. What this really means is that in the expression f(x), overload resolution has to run three different times. If we play by the current rules of C++, the only way this can make sense is if we basically unroll the loop into three different loop bodies, before we try to figure out what the types of the expressions are.
What if the code is actually
for (const auto & x : my_tuple) {
auto y = f(x);
}
auto is not magic, it doesn't mean "no type info", it means, "deduce the type, please, compiler". But clearly, there really need to be three different types of y in general.
On the other hand, there are tricky issues with this kind of thing -- in C++ the parser needs to be able to know what names are types and what names are templates in order to correctly parse the language. Can the parser be modified to do some loop unrolling of constexpr for loops before all the types are resolved? I don't know but I think it might be nontrivial. Maybe there is a better way...
To avoid this issue, in current versions of C++, people use the visitor pattern. The idea is that you will have an overloaded function or function object and it will be applied to each element of the sequence. Then each overload has its own "body" so there's no ambiguity as to the types or meanings of the variables in them. There are libraries like boost::fusion or boost::hana that let you do iteration over heterogenous sequences using a given vistior -- you would use their mechanism instead of a for-loop.
If you could do constexpr for with just ints, e.g.
for (constexpr i = 0; i < 10; ++i) { ... }
this raises the same difficulty as heterogenous for loop. If you can use i as a template parameter inside the body, then you can make variables that refer to different types in different runs of the loop body, and then it's not clear what the static types of the expressions should be.
So, I'm not sure, but I think there may be some nontrivial technical issues associated with actually adding a constexpr for feature to the language. The visitor pattern / the planned reflection features may end up being less of a headache IMO... who knows.
Let me give another example I just thought of that shows the difficulty involved.
In normal C++, the compiler knows the static type of every variable on the stack, and so it can compute the layout of the stack frame for that function.
You can be sure that the address of a local variable won't change while the function is executing. For instance,
std::array<int, 3> a{{1,2,3}};
for (int i = 0; i < 3; ++i) {
auto x = a[i];
int y = 15;
std::cout << &y << std::endl;
}
In this code, y is a local variable in the body of a for loop. It has a well-defined address throughout this function, and the address printed by the compiler will be the same each time.
What should be the behavior of similar code with constexpr for?
std::tuple<int, long double, std::string> a{};
for (int i = 0; i < 3; ++i) {
auto x = std::get<i>(a);
int y = 15;
std::cout << &y << std::endl;
}
The point is that the type of x is deduced differently in each pass through the loop -- since it has a different type, it may have different size and alignment on the stack. Since y comes after it on the stack, that means that y might change its address on different runs of the loop -- right?
What should be the behavior if a pointer to y is taken in one pass through the loop, and then dereferenced in a later pass? Should it be undefined behavior, even though it would probably be legal in the similar "no-constexpr for" code with std::array showed above?
Should the address of y not be allowed to change? Should the compiler have to pad the address of y so that the largest of the types in the tuple can be accommodated before y? Does that mean that the compiler can't simply unroll the loops and start generating code, but must unroll every instance of the loop before-hand, then collect all of the type information from each of the N instantiations and then find a satisfactory layout?
I think you are better off just using a pack expansion, it's a lot more clear how it is supposed to be implemented by the compiler, and how efficient it's going to be at compile and run time.
Here's a way to do it that does not need too much boilerplate, inspired from http://stackoverflow.com/a/26902803/1495627 :
template<std::size_t N>
struct num { static const constexpr auto value = N; };
template <class F, std::size_t... Is>
void for_(F func, std::index_sequence<Is...>)
{
using expander = int[];
(void)expander{0, ((void)func(num<Is>{}), 0)...};
}
template <std::size_t N, typename F>
void for_(F func)
{
for_(func, std::make_index_sequence<N>());
}
Then you can do :
for_<N>([&] (auto i) {
std::get<i.value>(t); // do stuff
});
If you have a C++17 compiler accessible, it can be simplified to
template <class F, std::size_t... Is>
void for_(F func, std::index_sequence<Is...>)
{
(func(num<Is>{}), ...);
}
In C++20 most of the std::algorithm functions will be constexpr. For example using std::transform, many operations requiring a loop can be done at compile time. Consider this example calculating the factorial of every number in an array at compile time (adapted from Boost.Hana documentation):
#include <array>
#include <algorithm>
constexpr int factorial(int n) {
return n == 0 ? 1 : n * factorial(n - 1);
}
template <typename T, std::size_t N, typename F>
constexpr std::array<std::result_of_t<F(T)>, N>
transform_array(std::array<T, N> array, F f) {
auto array_f = std::array<std::result_of_t<F(T)>, N>{};
// This is a constexpr "loop":
std::transform(array.begin(), array.end(), array_f.begin(), [&f](auto el){return f(el);});
return array_f;
}
int main() {
constexpr std::array<int, 4> ints{{1, 2, 3, 4}};
// This can be done at compile time!
constexpr std::array<int, 4> facts = transform_array(ints, factorial);
static_assert(facts == std::array<int, 4>{{1, 2, 6, 24}}, "");
}
See how the array facts can be computed at compile time using a "loop", i.e. an std::algorithm. At the time of writing this, you need an experimental version of the newest clang or gcc release which you can try out on godbolt.org. But soon C++20 will be fully implemented by all the major compilers in the release versions.
This proposal "Expansion Statements" is interesting and I will provide the link for you to read further explanations.
Click this link
The proposal introduced the syntactic sugar for... as similar to the sizeof... operator. for... loop statement is a compile-time expression which means it has nothing to do in the runtime.
For example:
std::tuple<int, float, char> Tup1 {5, 3.14, 'K'};
for... (auto elem : Tup1) {
std::cout << elem << " ";
}
The compiler will generate the code at the compile-time and this is the equivalence:
std::tuple<int, float, char> Tup1 {5, 3.14, 'K'};
{
auto elem = std::get<0>(Tup1);
std::cout << elem << " ";
}
{
auto elem = std::get<1>(Tup1);
std::cout << elem << " ";
}
{
auto elem = std::get<2>(Tup1);
std::cout << elem << " ";
}
Thus, the expansion statement is not a loop but a repeated version of the loop body as it was said in the document.
Since this proposal isn't in C++'s current version or in the technical specification (if it's accepted). We can use the alternative version from the boost library specifically <boost/hana/for_each.hpp> and use the tuple version of boost from <boost/hana/tuple.hpp>. Click this link.
#include <boost/hana/for_each.hpp>
#include <boost/hana/tuple.hpp>
using namespace boost;
...
hana::tuple<int, std::string, float> Tup1 {5, "one", 5.55};
hana::for_each(Tup1, [](auto&& x){
std::cout << x << " ";
});
// Which will print:
// 5 "one" 5.55
The first argument of boost::hana::for_each must be a foldable container.
Why isn't a for-loop a compile-time expression?
Because a for() loop is used to define runtime control flow in the c++ language.
Generally variadic templates cannot be unpacked within runtime control flow statements in c++.
std::get<i>(t);
cannot be deduced at compile time, since i is a runtime variable.
Use variadic template parameter unpacking instead.
You might also find this post useful (if this not even remarks a duplicate having answers for your question):
iterate over tuple
Here are two examples attempting to replicate a compile-time for loop (which isn't part of the language at this time), using fold expressions and std::integer_sequence. The first example shows a simple assignment in the loop, and the second example shows tuple indexing and uses a lambda with template parameters available in C++20.
For a function with a template parameter, e.g.
template <int n>
constexpr int factorial() {
if constexpr (n == 0) { return 1; }
else { return n * factorial<n - 1>(); }
}
Where we want to loop over the template parameter, like this:
template <int N>
constexpr auto example() {
std::array<int, N> vals{};
for (int i = 0; i < N; ++i) {
vals[i] = factorial<i>(); // this doesn't work
}
return vals;
}
One can do this:
template <int... Is>
constexpr auto get_array(std::integer_sequence<int, Is...> a) -> std::array<int, a.size()> {
std::array<int, a.size()> vals{};
((vals[Is] = factorial<Is>()), ...);
return vals;
}
And then get the result at compile time:
constexpr auto x = get_array(std::make_integer_sequence<int, 5>{});
// x = {1, 1, 2, 6, 24}
Similarly, for a tuple:
constexpr auto multiple_return_values()
{
return std::make_tuple(3, 3.14, "pi");
}
int main(void) {
static constexpr auto ret = multiple_return_values();
constexpr auto for_constexpr = [&]<int... Is>(std::integer_sequence<int, Is...> a) {
((std::get<Is>(ret)), ...); // std::get<i>(t); from the question
return 0;
}
// use it:
constexpr auto w = for_constexpr(std::make_integer_sequence<int, std::tuple_size_v<decltype(ret)>>{});
}

How to use auto keyword in C++

I have C++ code with a type auto:
auto T = reads a JSON
I need to print the content of the T using
cout << T << endl;
It is not working. Can you help me?
With C++11, you can declare a variable or an object without specifying its specific type by using auto.1 For example:
auto i = 42; // i has type int
double f();
auto d = f(); // d has type double
The type of a variable declared with auto is deduced from its initializer. Thus, an initialization is required:
auto i; // ERROR: can’t dedulce the type of i
Additional qualifiers are allowed. For example:
static auto vat = 0.19;
Using auto is especially useful where the type is a pretty long and/or complicated expression. For example:
vector<string> v; ... auto pos = v.begin(); // pos has type vector<string>::iterator
auto l = [] (int x) -> bool { // l has the type of a lambda ..., // taking an int and returning a bool };
In short auto can deduce any type .Your program is not working because it is possible that it is not able to parse JSON or compiler is old (where auto is not supported .Can you specifically let me know the error you got ?
auto in C++ means "set variable type for type of initialization expression", in your case whatever that "reads a JSON" expression returns. You cannot output that type to std::cout because operator<< is not defined for such type, there could be many possible reasons as operator not provided, you suppose to use something else, missing header etc. Solution would depend on actual type.
Ok ! Before telling you how to use auto, I must tell you it's one of the best features of C++11 & has made C++ even more efficient by :-
Reducing amount of code
Enforcing initialization
Increasing genericity (In C++17)
Firstly auto has only 1 job. It will deduce the type of an object by the value passed to it. For ex :-
auto x = 5;
This means that x is an integer whose value is 5. Whenever you are using auto you must initialize the variable (which is a good thing) & you cannot use auto on multiple types in a statement. For ex :-
auto x; // illegal ! x isn't initialized so compiler cannot dduce it's type
auto z=5, y=7; // legal because z & y are both integers
auto a=8, ch= 'c'; // illegal ! an integer & a character in a single statement, hence type deduction ambiguity
The cream of auto is not in intializing int, char, etc data types. It's more handy for classes like iterators. For ex :-
vector<int> v;
vector<int>::iterator i1 = v.begin();
auto i2 = v.begin(); // see how auto reduces the code length
This can be even more obvious in for loops :-
for (vector<int>::iterator i = v.begin(); i!=v.end(); ++i);
Can be reduced to :-
for (auto i = v.begin(), i!=v.end(); ++i);
If you are not happy with the above then this may inspire you to use auto :-
vector< map <int, vector<string> > >::iterator i1 = v.begin(); // where v is the vector of maps of ints & vectors of strings !!!!
auto i2 = v.begin();
The genericity I was talking about is in passing values to functions by auto. Like :-
void add (auto x, auto y)
{
cout << x+y << '\n';
}
This is not possible in current standards & has been proposed for C++17. This is likely to increase the generic ability of the functions without the use of templates. However this syntax is possible for lambda functions :-
auto l = [](auto x, auto y) { return x+y; } // legal from C++14 onwards
However be careful when using braces with lambda because you may think that :-
auto x = {5};
Is an integer but it is actually an intializer_list<int> type object. I can explain a hell lot about auto but I guess for now this is more than enough.

Tree in C++11 tuple with RTTI

I want to implement a simple tree in C++11 tuple with a Python fashion. In Python, we can use type(obj) to check run-time object type, and pass object with different type to one function, I have write pseudo code for calc(), how to do it in c++?
I try to print typeid(child1).name() and typeid(tree).name(), they are 'St5tupleIIciiEE' and 'St5tupleIIcS_IIciiEES0_EE'.
My environment is g++ 4.8.1. Thanks!
// pseudo code
int calc(tuple tree) {
symbol = type(get<0>(tree));
l_child = type(get<1>(tree));
r_child = type(get<2>(tree));
l = (type(l_child) == tuple) ? calc(l_child) : l_child;
r = (type(r_child) == tuple) ? calc(r_child) : r_child;
return l symbol r;
}
int main()
{
auto l_child = make_tuple('*', 1, 2);
auto r_child = make_tuple('-', 5, 1);
auto tree = make_tuple('+', l_child, r_child);
cout << calc(tree) << endl;
}
Python and C++ are very different languages. C++ is statically typed, Python is not. Transplanting Python techniques to C++ may or may not work. In this case it won't work.
In Python, there is only one tuple class, able to represent any tuple; in C++ there is an infinite number of tuple types, each one able to hold specific kinds of data. They are not interchangeable, as your experiment with typeid aptly demonstrates.
In C++, you cannot hold an arbitrary tree in a tuple. Write a tree class (or better, a class template).
Edit: technically, if you combine tuples with pointers and unions, you can get away with tuples. This is however not recommended. Your tree is going to be your central abstraction, exposing such low level details as pointers and unions is counterproductive and should be avoided. The C++ way is to write a class, stick to it.
It's unreal, since result of typeid().name is implementation-defined.
const char* name() const noexcept;
Returns: An implementation-defined ntbs.
However, here, you cannot use ternary operator, since calc(l_child) will be evaluated at compile-time, so if l_child is not tuple, compilation will be failed.
You can use some type-traits (or overloading), since tuple members are known at compile-time.
int calc(int value)
{
return value;
}
template<typename Left, typename Right>
int calc(const std::tuple<char, Left, Right>& tuple)
{
char symbol = std::get<0>(tuple);
Left l_child = std::get<1>(tuple);
Right r_child = std::get<2>(tuple);
int l = calc(l_child);
int r = calc(r_child);
return l /*symbol*/, r;
}
Live example