What Is This Crazy C++11 Syntax ==> Struct:Bar {} Foo {};

What is this crazy C++11 syntax == struct : bar {} foo {};?

First, we'll take a bog-standard abstract UDT (User-Defined Type):

struct foo { virtual void f() = 0; }; // normal abstract type
foo obj;
// error: cannot declare variable 'obj' to be of abstract type 'foo'

Let's also recall that we can instantiate the UDT at the same time that we define it:

struct foo { foo() { cout << "!"; } };          // just a definition

struct foo { foo() { cout << "!"; } } instance; // so much more
// Output: "!"

Let's combine the examples, and recall that we can define a UDT that has no name:

struct { virtual void f() = 0; } instance; // unnamed abstract type
// error: cannot declare variable 'instance' to be of abstract type '<anonymous struct>'

We don't need the proof about the anonymous UDT any more, so we can lose the pure virtual function. Also renaming instance to foo, we're left with:

struct {} foo;

Getting close.


Now, what if this anonymous UDT were to derive from some base?

struct bar {};       // base UDT
struct : bar {} foo; // anonymous derived UDT, and instance thereof

Finally, C++11 introduces extended initialisers, such that we can do confusing things like this:

int x{0};

And this:

int x{};

And, finally, this:

struct : bar {} foo {};

This is an unnamed struct deriving from bar, instantiated as foo with a blank initializer.

Have a C++ variable able to be either Class Foo or Class Bar

Instead of auto you'd want a pointer to the base class

int decider(int type) {
Printer* prt;
if (type == 1) {
prt = new CSV;
} else {
prt = new TXT;
}
prt->header();
}

but instead of raw pointers and new (since you are leaking memory from a missing delete) I'd instead use smart pointers here

#include <memory>

int decider(int type) {
std::unique_ptr<Printer> prt;
if (type == 1) {
prt = std::make_unique<CSV>();
} else {
prt = std::make_unique<TXT>();
}
prt->header();
}

As noted by @FredLarson you also need a virtual destructor in your base class

class Printer {
public:
virtual ~Printer() = default;
virtual void header() = 0;
};

you should also inherit publicly from the base class

class CSV : public Printer { 
...
};

class TXT : public Printer {
...
};

Global qualification in base specifier

This is just to do with parsing. From §2.5.3

If the input stream has been parsed into preprocessing tokens up to a given character, the next preprocessing token is the longest sequence of characters that could constitute a preprocessing token, even if that would cause further lexical analysis to fail.

Basically, it has to take the longest sequence of characters, so ::: is always parsed as :: : in the same way that x+++y is always parsed as x ++ + y.

This is referred to as Maximal Munch parsing.

Can someone tell me what this crazy c++ statement means in C#?

size_t is a typedef for an unsigned integer type. It is used for sizes of things, and may be 32 or 64 bits in size. The particular size of a size_t is implementation defined, but it is unsigned.

I suppose in C# you could use a 64-bit unsigned integer type.

All sizeof does is return the size in bytes of a C++ type. Every type takes up a certain quantity of room, and sizeof returns that size.

What your code is doing is computing the number of doubles (64-bit floats) that the DeltaTTable takes up. Essentially, it's ensuring that the table is larger than some size based on y, whatever that is.

There is no equivalent of sizeof in C#, nor does it need it. There is no reason for you to port this code to C#.

C++ syntax, is this a lambda

What a lambda looks like:

// This is the basics of a lambda expression.

[ /* Optional Capture Variables */ ]( /*Optional Parameters */ ) {
/* Optional Code */
}

So the simplest lambda is:

[](){}

What are the different parts:

Capture Variables:   Variables from the current visible scope
that can be used by the lambda.
Parameters: Just like a normal function, these are parameters
that are passed to the parameter when it is invoked.
Code: This is the code that is executed and uses the
above mentioned variables when the lambda is invoked.

I think it is useful to consider what is likely (not specified) going on behind the senes. A Lamda is just syntactic sugar for a functor (a callabale object).

  int main()
{
int data = 12;
// define the lambda.
auto lambda = [&data](int val){
std::cout << "Lambda: " << (val + data) << "\n";
};

lambda(2); // activate the lambda.
}

This is semantically equivalent to the following:

  class CompilerGeneratedClassNameLambda
{
int& data;
public:
CompilerGeneratedClassNameLambda(int& data)
: data(data)
{}
void operator()(int val) const {
std::cout << "Lambda: " << (val + data) << "\n";
}
};
int main()
{
int data = 12;
CompilerGeneratedClassNameLambda lambda(data);

lambda(2); // activate the lambda.
}

In your code. This part is the lambda:

[&p,buf](std::error_code ec, size_t n) {
std::cout << "Received " << n << " bytes (" << ec.message() << "): '";
std::cout.write(boost::asio::buffer_cast<char const*>(buf), n) << "'" << std::endl;
if (!ec) read_loop(p, buf);
}


Related Topics



Leave a reply



Submit