Define a enum-variabele after declaration - c++

I'm learning enumerations. I have the following problem: I don't understand, why this works:
enum {fahrrad = 1, Auto = 2} einFahrzeug;
int main() {
einFahrzeug = fahrrad;
but this doesn't:
enum {fahrrad = 1, Auto = 2} einFahrzeug;
einFahrzeug = fahrrad;
int main() { ...
I would be very happy about an answer

You can't assign stuff to variables outside of a function. More simple example:
#include <iostream>
int x;
x = 42;
int main()
{
std::cout << x << '\n';
}
This gives:
prog.cpp:4:1: error: ‘x’ does not name a type
x = 42;
^
Try it with ideone.com: https://ideone.com/A1K06A

Related

Boost transformed conversion to vector error

I am new to using boost adapters, I am using the following code for conversion of a vector one class to transformed version.
The return type of boost::transformed is not as per expectation. Can someone please illuminate as to what I am missing here:
class blabla
{
public:
int x;
};
class blabla2
{
public:
int y;
blabla2(int a)
{
y=a;
}
};
int main()
{
using namespace boost::adaptors;
std::vector<blabla> test;
auto foo = [](const blabla& A) -> std::pair<blabla2, double> {
return std::make_pair(blabla2(A.x), double(A.x));
};
const auto histogram = test | boost::adaptors::transformed(foo);
// std::vector<std::pair<blabla2, double>> should be return type?
std::vector<std::pair<blabla2, double>> histogramtest = histogram; ----> this line gives error unexpectedly. Why is it so?
std::pair<blabla2, double> x = histogram[0];
}
The line std::vector<std::pair<blabla2, double>> histogramtest = histogram; gives error
While std::pair<blabla2, double> x = histogram[0]; works correctly. Why is that so?
The return value is boost::transformed_range<decltype(foo), std::vector<blabla>>, not std::vector<std::pair<blabla2, double>>. If you want to achieve expected type, you should do something like that:
std::vector<std::pair<blabla2, double>> histogramtest;
boost::copy( test | transformed(foo), std::back_inserter(histogramtest));
You need to copy the range into a vector.
e.g.
#include "boost/range/adaptor/transformed.hpp"
#include "boost/range/algorithm.hpp"
#include <iostream>
#include <vector>
class blabla
{
public:
int x;
};
class blabla2
{
public:
int y;
blabla2(int a)
{
y = a;
}
};
int main()
{
std::vector<blabla> test = { {1}, {2}, {3} };
auto foo = [](const blabla& A) -> std::pair<blabla2, double> {
return std::make_pair(blabla2(A.x), double(A.x));
};
const auto test_range = test | boost::adaptors::transformed(foo);
std::vector<std::pair<blabla2, double>> test_output_vector;
boost::range::copy(test_range, std::back_inserter(test_output_vector));
for (const auto& [b, v] : test_output_vector) {
std::cout << b.y << ", " << v << "\n";
}
}

The using declaration and function default arguments

According to the C++ 17 Standard (10.3.3 The using declaration)
1 Each using-declarator in a using-declaration98 introduces a set of
declarations into the declarative region in which the
using-declaration appears.
and
10 A using-declaration is a declaration and can therefore be used
repeatedly where (and only where) multiple declarations are allowed.
and (The C++ 17 Standard, 11.3.6 Default arguments)
...When a declaration of a function is introduced by way of a
using-declaration (10.3.3), any default argument information
associated with the declaration is made known as well. If the function
is redeclared thereafter in the namespace with additional default
arguments, the additional arguments are also known at any point
following the redeclaration where the using-declaration is in scope.
So this program
#include <iostream>
void f( int x, int y = 20 )
{
std::cout << "x = " << x << ", y = " << y << '\n';
}
int main()
{
using ::f;
void f( int, int );
f( 10 );
return 0;
}
as expected compiles and outputs
x = 10, y = 20
In fact it is similar to the program
#include <iostream>
void f( int x, int y )
{
std::cout << "x = " << x << ", y = " << y << '\n';
}
int main()
{
void f( int, int = 20 );
void f( int, int );
f( 10 );
return 0;
}
Now it would be logical consistent that the following program also was valid.
#include <iostream>
void f( int x, int y = 20 )
{
std::cout << "x = " << x << ", y = " << y << '\n';
}
int main()
{
using ::f;
void f( int, int );
f( 10 );
void f( int = 10, int );
f();
return 0;
}
However this program does not compile.
On the other hand, consider the following program.
#include <iostream>
namespace N
{
int a = 10;
int b = 20;
void f( int, int = b );
}
int a = 30;
int b = 40;
void N::f( int x = a, int y )
{
std::cout << "x = " << x << ", y = " << y << '\n';
}
int main()
{
using N::f;
f();
return 0;
}
It compiles successfully and its output is
x = 10, y = 20
So could be the same principles applied to functions introduced by the using declaration?
What is the reason of that such an addition of default arguments is not allowed?
You can only declare new default arguments in the same scope as the original declaration. using does not change this.
For non-template functions, default arguments can be added in later declarations of a function in the same scope.
dcl.fct.default/4
I believe
any default argument information associated with the declaration is made known as well
doesn't mean the arguments are actually imported into the scope, it's just known that they do exist and can be used.
That would mean that void f( int = 10, int ); isn't adding to void f( int x, int y = 20 ), but is instead trying to add to void f( int, int ); which would be illegal as there isn't a default argument for the second parameter in the scope that the using declaration is in.

C++: array<> too many initializers

The following code is returning the compilation error below. I'm stuck understanding how there are too many initializers. This code works using vector<X>. Does anyone know why the error is being reported and how to resolve? Thanks
#include <iostream>
#include <array>
using namespace std;
struct X {
int x, y;
};
int main(int argc, char *argv[])
{
array<X,2> a0 = {{0,1}, {2,3}};
for (auto& p : a0) {
cout << p.x << endl;
cout << p.y << endl;
}
return 0;
}
Compilation:
g++ -pedantic -Wall test116.cc && ./a.out
test116.cc: In function ‘int main(int, char**)’:
test116.cc:11:34: error: too many initializers for ‘std::array<X, 2>’
array<X,2> a0 = {{0,1}, {2,3}};
Try
array<X,2> a0 = {{{0,1}, {2,3}}};
Note the extra set of braces.
It seems a bit odd but it's this way because the only member of array is the actual array:
template <class T, size_t N>
class array {
T val[N];
// ...
};
The constructors are all implicitly defined so that array ends up being a trivially constructable type.
You may use one of the following initializations because std::array is an aggregate that contains another aggregate as its data member.
array<X,2> a0 = { { { 0, 1 }, { 2, 3 } } };
array<X,2> a0 = { 0, 1, 2, 3 };
array<X,2> a0 = { { 0, 1, 2, 3 } };
array<X,2> a0 = { { 0, 1, { 2, 3 } } };
array<X,2> a0 = { { { 0, 1 }, 2, 3 } };
I found that my problem is related to the version of g++,9.4.0 is ok and 5.4.0 not.version of g++.By the way, the version of g++ is associated with the system version generally.

Passing variable length argument to function C++

I am trying to create a function that accepts variable number of arguments. But I am getting error in expression decltype(std::initializer_list::size_type) res1=0; as error: expected primary-expression before 'decltype'. The purpose is to declare appropriate variable type that can hold sum of the list (although this declaration will create big enough variable to hold all elements of the list only and not their sum). How can I do this?
Also, how can I make appropriate function return type to return res1 instead of void?
#include <iostream>
#include <initializer_list>
void sum1(std::initializer_list<int> lst1)
{
decltype(std::initializer_list::size_type) res1=0;
for(auto v1:lst1)
{
res1 += v1;
}
std::cout<<" sum = \n"<<res1;
}
int main()
{
sum1({1,2,3,4,5,6,7,8,9,10});
//auto b = sum1({1,2,3,4,5,6,7,8,9,10});
return 0;
}
size_type is not needed for anything in your function. The initializer_list has type int, therefore res1 should be an int and your return type should be int. If you really want to derive the value type from the initializer_list then do so like this:
#include <iostream>
#include <initializer_list>
auto sum1(std::initializer_list<int> lst1)
{
typename std::initializer_list<int>::value_type res1 = 0;
for(auto v1:lst1)
{
res1 += v1;
}
return res1;
}
int main()
{
sum1({1,2,3,4,5,6,7,8,9,10});
auto b = sum1({1,2,3,4,5,6,7,8,9,10});
std::cout << b << std::endl;
return 0;
}
If you want the function to be generic, in which case it is necessary to derive the value type, then the template function looks like this.
#include <iostream>
#include <initializer_list>
template<typename T>
auto sum1(std::initializer_list<T> lst1)
{
typename std::initializer_list<T>::value_type res1 = 0;
for(auto v1:lst1)
{
res1 += v1;
}
return res1;
}
int main()
{
sum1({1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9,10.10});
auto b = sum1({1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9,10.10});
std::cout << b << std::endl;
return 0;
}
Following is corrected code.
#include <iostream>
#include <initializer_list>
int sum1(std::initializer_list<int> lst1)
{
int res1=0;
for(auto v1:lst1)
{
res1 += v1;
}
return res1;
}
int main()
{
std::cout<<" sum = "<<sum1({1,2,3,4,5,6,7,8,9,10});
//auto b = sum1({1,2,3,4,5,6,7,8,9,10});
return 0;
}
You can see working here.
Note: You can change the type of res0 to long or other type if result is not in the limits of int. Also, Change the return type of function sum1 accordingly.

C++ and currying

I've the code:
#include <iostream>
using namespace std;
auto fn = ([](int x){
return [x](int y) {
return x * y;
};
});
int main() {
int i = fn(2)(4); // 8
cout << i << endl;
return 0;
}
This code works fine.
However, I want to call a second function later like:
auto i = fn(2);
i(4); //error: 'i' cannot be used as a function
Are there any way to call the last function later and then bind with the first call?
The following works as expected
#include <iostream>
using namespace std;
auto fn = [](int x){
return [x](int y) {
return x * y;
};
};
int main() {
auto i = fn(2)(4); // 8
cout << i << endl;
auto j = fn(2);
cout << j(4) << endl;
return 0;
}
ADD
By the way gcc 4.5 with -std=c++0x gives the following error if you use int instead of auto:
currying.cpp:17:17: error: cannot convert ‘<lambda(int)>::<lambda(int)>’ to ‘int’ in initialization
currying.cpp:19:16: error: ‘j’ cannot be used as a function
which is an "obvious" and useful information to get what's going wrong.
The result of fn is not an integer, so you cannot assign fn(2) to an integer (don't even know why that compiles).
You should be able to do auto i = fn(2);
This works for me:
int main() {
auto i = fn(2);
cout << i(4) << endl; // prints 8
return 0;
}