Random number example from Stroustrup has compilation error - c++

I'm using this random number example from Stroustrup C++ 4th Ed Page 1182. The compiler is reporting an error on the line with auto, stating that auto cannot be used with non-static members of classes. I'm confused on what the type of this bind results in. Does anyone know how to resolve the error so the random number generator can be used?
#include <random>
using namespace std;
class Rand_int {
public: // added
Rand_int(int lo, int hi) : p{lo,hi} { }
int operator()() const { return r(); }
private:
uniform_int_distribution<>::param_type p;
auto r = bind(uniform_int_distribution<>{p},default_random_engine{});
};
int main()
{
Rand_int ri {0,10};
int pz = ri();
return 0;
}
Compilation error:
clang++ -Wall -std=c++11 -pedantic test252.cc && ./a.out
test252.cc:11:5: error: 'auto' not allowed in non-static class member
auto r = bind(uniform_int_distribution<>{p},default_random_e...
^~~~

You can't use auto for the type of a non-static member of a class, so the code example is wrong.
Instead, you can do:
class Rand_int {
private:
std::function<int()> r = bind(uniform_int_distribution<>{p},default_random_engine{});
// ...
};
This converts the return type of std::bind to a void function returning an int, which is the desired behavior.
Here's a demo.

Related

dynamic_cast<> question using Stroustrup example

I'm testing a dynamic_cast<> example in Stroustrup C++ 4th Ed Page 642 and it does not compile. I'm using the following picture directly from the book trying to learn how it works. Does anyone know if this is Eratta (its not in his published errata doc) or I have misread something?
Stroustrup Graphic, dashed line represents protected:
#include <iostream>
using namespace std;
// H = Ival_box
class H {
};
// G = Ival_slider
class G : public H {
};
// I = BBwindow
class I {
};
// F = BB_slider
class F : public I {
};
// X = BB_ival_slider
class X : public G, protected F {
};
int main(int argc, char *argv[])
{
// works
X xx{};
if (auto p = dynamic_cast<G*>(&xx))
cout << "X*...G*" << endl;
// works
G gg{};
if (auto p = dynamic_cast<H*>(&gg))
cout << "G*...H*" << endl;
// compilation error, 'I' is not polymorphic
I ii{};
if (auto p = dynamic_cast<H*>(&ii))
cout << "I*...H*" << endl;
return 0;
}
Compilation and results:
clang++ -std=c++11 -pedantic -Wall test164.cc && ./a.out
test164.cc:31:18: error: 'I' is not polymorphic
if (auto p = dynamic_cast<H*>(&ii))
^ ~~~
1 error generated.
Compilation and results with error commented out:
clang++ -std=c++11 -pedantic -Wall test164.cc && ./a.out
X*...G*
G*...H*
The error explains what is wrong. Dynamic cast is only allowed for polymorphic types (except when casting upwards in inheritance hierarchy).
A class is polymorphic only if it has at least one virtual function. I does not have any virtual functions. Therefore it is not polymorphic. You must add a virtual function to I in order for this to work.
Note that even then, dynamic_cast<H*>(&ii) can never be a non-null pointer (i.e. true) because ii is not a base sub object of an object of type H.

c++ enum scope failed to compile with -std=c++98, but ok with -std=c++11

A simple program as below, no c++11 syntax at all (e.cpp)
#include<iostream>
using namespace std;
namespace m{
class my{
public:
enum A{
u=1,
v=2,
w=3
};
static A f(A a){
return (A)(a + A::u);
}
};
int main(){
using namespace m;
my::A r=my::f(my::u);
return 0;
}
Using g++4.1.2 to compile it:
e.cpp:17:2: warning: no newline at end of file
e.cpp: In static member function ‘static m::my::A m::my::f(m::my::A)’:
e.cpp:11: error: expected primary-expression before ‘)’ token
e.cpp:11: error: ‘A’ is not a class or namespace
Using g++4.9.2 with -std=c++98
g++ e.cpp -std=c++98
e.cpp: In static member function ‘static m::my::A m::my::f(m::my::A)’:
e.cpp:11:36: error: ‘A’ is not a class or namespace
static A f(A a){return (A)(a + A::u);}
^
But using -std=c++11 is ok:
g++ e.cpp -std=c++11
To make it compile using c++98, I change it to avoid "A::" to be:
static A f(A a){return (A)(a + u);}
So seems that under c++98, the embeded enum class is not recognized inside a class, while in c++11 it works. Is this a difference in enum resolution, or some previous syntax bug in c++98 standard?
Enum values are not scoped by the enum type (either in C++98 or C++11). In the following example:
namespace N {
enum E { X };
}
X is directly in the scope of namespace N. Its fully qualified identifier would be ::N::X.
This behaviour was changed by C++11, where following the same definition, the identifier of X can also be referred using ::N::E::X:
[dcl.enum/11]
An enumerator declared in class scope can be referred to using the class member access
operators (::, . (dot) and -> (arrow)), see 5.2.5. [ Example:
struct X {
enum direction { left=’l’, right=’r’ };
int f(int i) { return i==left ? 0 : i==right ? 1 : 2; }
};
void g(X* p) {
direction d; // error: direction not in scope
int i;
i = p->f(left); // error: left not in scope
i = p->f(X::right); // OK
i = p->f(p->left); // OK
// ...
}
—end example ]
The enumeration name could not be used to qualify an enumerator prior to C++11. So there is no bug in C++98 mode, the code is just ill-formed.
You are correct in deducing the rules have changed.
The C++ FAQ lists the changes made to enumerations in C++11, and cites the proposals that drove those changes.

The body of constexpr function not a return-statement

In the following program, I have added an explicit return statement in func(), but the compiler gives me the following error:
m.cpp: In function ‘constexpr int func(int)’:
m.cpp:11:1: error: body of constexpr function ‘constexpr int func(int)’ not a return-statement
}
This is the code:
#include <iostream>
using namespace std;
constexpr int func (int x);
constexpr int func (int x)
{
if (x<0)
x = -x;
return x; // An explicit return statement
}
int main()
{
int ret = func(10);
cout<<ret<<endl;
return 0;
}
I have compiled program in a g++ compiler using the following command.
g++ -std=c++11 m.cpp
I have added return statement in function, then Why I got above error?
Prior to C++14, the body of a constexpr function must consist solely of a return statement: it cannot have any other statements inside it. This works in C++11 :
constexpr int func (int x)
{
return x < 0 ? -x : x;
}
In C++14 and up, what you wrote is legal, as are most other statements.
Source.
C++11's constexpr functions are more restrictive than that.
From cppreference:
the function body must be either deleted or defaulted or contain only the following:
null statements (plain semicolons)
static_assert declarations
typedef declarations and alias declarations that do not define classes or enumerations
using declarations
using directives
exactly one return statement.
So you can say this instead:
constexpr int func (int x) { return x < 0 ? -x : x; }
static_assert(func(42) == 42, "");
static_assert(func(-42) == 42, "");
int main() {}
Note that this restriction was lifted in C++14.

Incorrect use of explicit keyword in c++

I wanted to create a class MPSList where constructor has an explicit keyword associated with it.
Following is the bare minimal code:
class MPSList {
public:
explicit MPSList(int n) : n_(n) {
mpsL.resize(n_, std::vector<MPSNode>{});
std::cout << mpsL.size() << std::endl;
}
private:
struct MPSNode {
double s_;
};
std::vector<std::vector<MPSNode>> mpsL;
int n_ = -1;
};
CPP file that creates the object of MPSList class.
#include <iostream>
#include "MPSList.hpp"
int main() {
double n = 10.9;
MPSList mps(n);
}
On compiling the above CPP file, I had expected to see an error in initializing the object. As I am passing a double whereas the constructor is explicitly expecting an int.
Command to compile:
g++ -std=c++14 -I../include test.cpp
./a.out
Explicit stops the compiler from doing something like this:
void fn(MPSNode x); // or void fn(const MPSNode& x)
fn(3.0);
The above snippet would compile if you didn't use explicit, and the line that calls fn is equivalent to:
fn(MPSNode(3.0));
This is an implicit conversion from double to MPSNode. Narrowing conversions have relatively little to do with it.
However, you will find that the following will not compile:
MPSList mps{n};
Use uniform initialisation syntax if you want to catch problems like that.

Undefined reference to static function pointer member in c++, what am I doing wrong?

please consider these files:
p.h:
#ifndef _p_h_
#define _p_h_
class p{
public:
static void set_func(int(*)());
private:
static int (*sf)();
};
#endif
p.cpp:
#include "p.h"
#include <cstdio>
int (p::*sf)() = NULL; //defining the function pointer
void p::set_func(int(*f)()){
sf = f;
}
main.cpp:
#include "p.h"
#include <iostream>
int function_x(){
std::cout << "I'm function_x()" << std::endl;
return 1234;
}
int main(){
p::set_func(function_x);
}
when compiling, I get this:
$ g++ -o pp main.cpp p.cpp
/tmp/ccIs0M7r.o:p.cpp:(.text+0x7): undefined reference to `p::sf'
collect2: ld returned 1 exit status
but:
$ g++ -c -o pp p.cpp
compiles right.
What's wrong with the code? I just can't find where the problem is, please your help will be more than appreciated.
Thanks.
Your attempt at defining p::sf is incorrect – yours is a definition of a global variable named sf that is of type int (p::*)(), i.e. a pointer to a member function. Consequently p::sf remains undefined, hence the linker error.
Try this instead:
int (*p::sf)() = 0;
// or,
typedef int (*p_sf_t)();
p_sf_t p::sf = 0;
The difference is because error only occurs when you actually link the program. The problem is in your declaration of the static function pointer. The correct syntax is:
int (*p::sf)() = NULL; //defining the function pointer
You define a member function pointer and not a function pointer. I'm not sure what the correct syntax is, but I would have tried something like this:
int (*p::sf)() = NULL;
I will not give another answer (ildjarn answer is correct) but i will suggest you another way of achieving the same without static initialization (and the burdens it implies)
class p{
public:
typedef int (*func_t)();
static void set_func(func_t v) {
func_t& f = getFuncRef();
f = v;
}
static void call_func() {
func_t& f = getFuncRef();
assert( f != 0);
f();
}
private:
static func_t& getFuncRef() {
static func_t sf = 0;
return sf;
}
};
in this way you delegate the static initialization to a static function variable, which doesn't have the initialization order problems that affect static data variables, and is lazy-initialised