I was browsing some of Ubuntu's Mir examples and i stumbled upon code that i couldn't understand.
struct DemoServerConfiguration : mir::DefaultServerConfiguration
{
What is going on here ": mir::DefaultServerConfiguration"?
Inside that struct there's this
std::shared_ptr<msh::PlacementStrategy> the_shell_placement_strategy()
{
return shell_placement_strategy(
[this]
{
return std::make_shared<me::FullscreenPlacementStrategy>(the_display());
});
}
Same story here, i don't understand the syntax the unclear parts are:
<msh::PlacementStrategy> the_shell_placement_strategy()
and
return shell_placement_strategy(
[this]
{
Inside the same struct again
std::initializer_list<std::shared_ptr<mi::EventFilter> const> the_event_filters() override
{
return filter_list;
}
Why the multiple <> <> <> nested? Why the the_event_filters() there?
And the last piece
mir::run_mir(config, [&config, &wm](mir::DisplayServer&)
{
code
});
Unclear part
(config, [&config, &wm](mir::DisplayServer&)
);
First example
That's simply a case of inheriting from an internal type:
class C
{
public:
class Internal
{
};
};
class D : public C::Internal
{
// D derives from Internal class, which is a member of C class
};
The :: is an operator of scope resolution. The expression A::B means: "B, which is a member of A". :: works for classes, structures and namespaces.
Second example
That's a little bit more complicated.
std::shared_ptr<msh::PlacementStrategy> the_shell_placement_strategy()
{
return shell_placement_strategy(
[this]
{
return std::make_shared<me::FullscreenPlacementStrategy>(the_display());
});
}
Let's break it to parts.
std::shared_ptr<msh::PlacementStrategy> the_shell_placement_strategy()
This is a function / method the_shell_placement_strategy, which returns a result of type std::shared_ptr (generic class parametrized with msh::PlacementStrategy - see previous point).
return shell_placement_strategy(
It returns result of calling the shell_placement_strategy...
[this]
{
return std::make_shared<me::FullscreenPlacementStrategy>(the_display());
}
...which takes a lambda (nameless function) as a parameter. That nameless function wants to have access to this (thus [this]) and returns result of call to generic function std::make_shared, parametrized with me::FulscreenPlacementStrategy and called with parameter being a result of calling the_display() method / function.
You may read about lambdas elsewhere, but I'll include a short explanation for reference:
[access-specification](parameters){ body }
Where:
access-specification defines the relation between lambda and local variables. For example, [a] means, that lambda will have access to local variable a by value; [&a] - the same, but by reference; [&] - lambda will have access to all local variables by reference and so on.
parameters - regular definition of function parameters
body - regular body of lambda.
The lambda notation is a part of C++11 standard.
Last example
You now should be able to interpret this example:
mir::run_mir(config, [&config, &wm](mir::DisplayServer&)
{
code
});
Thats:
A call to run_mir method (or function), which is a part of mir class (or namespace);
With two parameters: config and a function, which accepts two parameters;
config is passed as first parameter;
A lambda is passed by the second parameter.
Now the lambda:
It wants to access by reference two local variables: config and wm
It accepts one parameter of type mir::DisplayServer& (there's no name for this parameter, so it seems, that it does not actually use it
It does <code> :)
First case, it is private inheritance. DemoServerConfiguration is derived from mir::DefaultServerConfiguration, where mir is probably a namespace (but could also be a class that declares the inner class DefaultServerConfiguration.
Second case, you are looking at lambda expression definition. You can read some introduction here.
Finally, the initializer lists are actually another feature introduced in C++11 standard (not yet supported by most of the compilers, AFAIK). Some introduction about them here.
mir::DefaultServerConfiguration
Here mir could be a namespace or a class inside which DefaultServerConfiguration is defined. So for example, it could be this:
namespace mir
{
class DefaultServerConfiguration
{
/*...*/
};
}
Or this,
class mir
{
public:
class DefaultServerConfiguration
{
/*...*/
};
}
In both cases, you could access the class DefaultServerConfiguration as:
mir::DefaultServerConfiguration
The same is true for other cases.
struct DemoServerConfiguration : mir::DefaultServerConfiguration
{
Here DemoServerConfiguration is a class deriving from mir::DefaultServerConfiguration. Make sense?
You also notice this in case of std::make_shared. Here std is a namespace defined by C++ Standard Library inside which the library defines make_shared function template.
Hope that helps.
Related
I have a CRTP class where for API clarity during refactoring, I want to have a named anonymous struct containing methods, instead of having all methods at class scope. The problem is, these methods need access to the outer scope. For example:
template<typename T>
class sample_class {
public:
struct {
void do_something() {
auto& result = get_ref().something_else(); //get_ref() out of inner struct scope
...
}
} inner;
private:
T& get_ref() { return static_cast<T&>(*this); }
};
Is there some technique to make this work? Specifically C++14 and gcc7, since I do not believe anonymous structs are technically standard compliant.
A class in another class has no implicit pointer to the enclosing class's this pointer.
If you want it to have the pointer to an instance of the enclosing class, explicitly store it.
struct {
void do_something() {
auto& result = p_sample->get_ref().something_else(); //get_ref() out of inner struct scope
...
}
sample* p_sample;
} inner;
or pass in a pointer to the methods:
void do_something(sample* psample) {
auto& result = p_sample->get_ref().something_else(); //get_ref() out of inner struct scope
...
}
there are ways to use pointer arithmetic to generate what appears to be a pointer to the outer class, but they are trapped with extremely complex and dangerous rules in C++.
Other than some access/naming rules and the like, classes defined in other classes are not magic. They could (in theory) exist in other environments; the inner could live on the stack somewhere, not within a sample.
Yes, you subtract the result of offsetof from this:
auto &self = *reinterpret_cast<sample_class *>(reinterpret_cast<char *>(this) - offsetof(sample_class, inner));
This might technically be UB (see reachability rules for std::launder), but should be good enough in practice.
But I argue that getting a nice-looking method name doesn't warrant this hackery. Just replace inner.do_something() with something like inner_do_something().
I'm having a class that contains a function pointer. I would like to initialize various instances of the class statically but I can't figure out the correct syntax for this.
Let's say, this is my class
class fooClass
{
int theToken;
string theOutput;
bool (*theDefault)( void );
};
I now would like to create a static instance of this, like this…
fooClass test
{
1,
"Welcome",
(){ return (theToken & 1 ) ? true : false; }
};
As I said, I can't figure out the proper syntax for the function pointer line. Or is it even possible like this? I'd really like not having to break out every function I create this way into its own function declaration.
What I'm trying to do is, allow each instance to have a unique default function because each instance represents a unique data-driven building block of a bigger system. The code I put in there is just for illustrative purposes. This default function will access certain global variables as well as some of the member variables and if need be I could pass this into the function.
Could someone point me in the right direction how I'd have to write the initialization for it to work under C++14?
If you want to refer to struct members inside the function, you cannot do with just a plain function pointer not receiving any argument, as it doesn't receive the this pointer.
My advice is to at very least change it to a pointer to a function taking the instance as an argument, then in initialization you can pass a capture-less lambda (which can be converted to a plain function pointer):
class fooClass
{
int theToken;
string theOutput;
bool (*theDefault)( fooClass *that);
// you may provide a helper for ease of use
bool Default() { return theDefault(this);}
};
fooClass test
{
1,
"Welcome",
[] (fooClass *that){ return (that->theToken & 1 ) ? true : false; }
};
You can also use an std::function<bool(fooClass*)> to allow even functors, lambdas with captures & co. if you are ok with the increased overhead.
You may be tempted to use a plain std::function<bool()> instead, and use a lambda capturing the instance by reference, such as
fooClass test
{
1,
"Welcome",
[&test] (){ return (test->theToken & 1 ) ? true : false; }
};
This does work, but is extremely dangerous if test happens to be copied, as theDefault will still refer to test even in the copy (and even after the original will have been destroyed).
(incidentally, this is how OOP is often done in languages such as Lua, but there (1) objects are not copied and (2) automatic memory management makes sure that closures "keep alive" the objects they capture)
In the header, I have
class CSomeClass
{
const GUID m_guid;
public:
CSomeClass();
///...
}
And in the source file
CSomeClass::CSomeClass()
, m_guid(
[]() {
GUID g;
::CoCreateGuid(&g);
return g;
}()
)
{
}
As you know Guids can be used as identifications not meant to be changed. Given the ::CocreateGuid() function provides what I want as an output parameter, instead of returning it, I cannot use directly a simple call to the function for initializing the m_guid member field, that is constant.
So, a consequence of its constness, is that it must be initialized before the opening bracket in initializer list, and therefore not be simply assigned with a call to ::CocreateGuid() in the constructor body.
Is there a simpler way to initialize it than this lambda expression?
When the lambda expression is correct, I would use a helper function for that:
GUID create_guid()
{
GUID g;
::CoCreateGuid(&g);
return g;
}
CSomeClass::CSomeClass() : m_guid(create_guid()) {}
In addition, create_guid() has a meaning by itself and could be reused (even if making it a implementation detail is possible/correct).
You should consider wrapping the GUID in its own class:
class CGUID
{
public:
CGUID()
{
CoCreateGuid(m_guid);
}
const GUID& guid() const { return m_guid; }
// Maybe some useful functions:
bool operator==(const CGUID&) const;
private:
GUID m_guid;
};
Now you can use the above as a member:
class CSomeClass
{
const CGUID m_guid;
...
Here we abstract your pattern:
template<class A>
A co_make( HRESULT(*f)(A*) {
A a;
HRESULT hr = f(&a);
Assert(SUCCEEDED(hr));
if (!SUCCEEDED(hr))
throw hr;
return a;
}
CSomeClass::CSomeClass()
m_guid(
co_make(&::CoCreateGuid)
)
{}
where we detect failure and assert then throw if that is the case.
I'm not sure this is simpler.
Really, write a GUID make_guid() function, stick it in some header, and call it.
Your proposal is the simplest way to initialize the constant instance member.
Don't get scared of lambdas, as a matter of fact, in general it is a new style recommendation to use lambdas for complex initializations of constants and references because they share the property of only being initialized at the point of declaration (or instance member initialization in the initializer list).
Furthermore, your code triggers the "named return value optimization" and there is no copy construction at the return from the lambda.
The interface to CoCreateGuid is deficient because it requires an output argument.
If you insist on not using the lambda, I think the next most practical alternative is to, in the constructor body, de-constify using const_cast to pass it to CoCreateGuid.
Mind you that one you enter the body of a constructor the language considers all individual members to have been properly initialized, and will invoke destructors for them should an exception happens, this makes a very big difference whether something is initialized in the initializer list or left with a binary pattern of garbage.
Finally, unfortunately you can't just call CoCreateGuid with a de-constified reference to m_guid in the lambda, because the lambda will still return a value and that will overwrite the member. It is essentially the same as what you already wrote (with the exception of the default constructor of g)
It would be simpler if you declare m_guid as a mutable instance member as opposed to const. The difference is that mutable are like a const for users of a class but a perfectly fine lvalue within the class
I have to create objects of three-four classes, all inherited from one base class, but some of the objects need to have different behavior - like complete change of one function; I can do this through more inheritance and polymorphism, but it doesn't seem like a good idea.
My first solution was to use specialized templates(for every nonstandard case), but then I have though about lambdas as template parameter(like here: Can we use a lambda-expression as the default value for a function argument? ) and use them instead class method(like here: C++11 lambda and template specialization ) - for me it's much better solution, because I only have to pass lambda for every weird situation:
auto default_lambda = [&]() -> int {return this->Sth;};
template<typename functor = decltype(default_lambda)>
class SomeClass{
...
Problem is with this pointer - method which I want to change need access to non-static methods and lambda is defined outside of non-static method. Moreover, I can't pass reference to class to lambda, because it's a template class(or maybe I'm wrong?).
Of course, I can use specialized template or just function pointers, but I really like solution with lambdas and I consider it much more fine than my other ideas.
Is there any way to "avoid" this problem? Or maybe my idea was bad all along?
There are at least three obvious problems with your approach:
The class SomeClass won't get access to private members, i.e. use of this is out of question.
You attempt to bind this from the context but there is no context i.e. nothing bind to. You will have to pass the object to dealt with a function parameter.
You only specified a type of the function object but no instance, i.e. you won't be able to use it later.
That said, it seems you could just use the type of a custom function object type rather than some lambda function (sure, this is absolutely unsexy but in return it actually works):
struct default_lambda {
template <typename T>
int operator()(T const& o) const { return o.x(); }
};
template <typename F = default_lambda>
class SomeClass {
...
};
If you need complete change of one function, you have two choices:
One virtual function, using perhaps local classes + type erasure if you have many such objects and you don't want to create many namespace scope types:
std::function, which can be rebound later if you wish.
Example code for the first solution (you can even make this a template):
std::unique_ptr<my_base2> get_an_object()
{
class impl : public my_base2
{
void my_virtual_function() { blah blah; }
};
return std::unique_ptr<my_base2>(new impl);
}
Both are generally superior to templates in this situation (but without context it is hard to tell).
Let's say we're given this class with an inner struct.
class Some {
public:
struct Crap{};
Crap Process(Crap& c);
}
Some::Crap Some::Process(Crap& crap) { Crap moreCrap = .. }
It makes sense to me that the return type (Some::Crap) in "Process" is scoped.
It makes sense to me that no scoping is needed inside the body of "Process".
I do not understand why the inner struct parameter of Process (Crap& crap) does not require scoping.
Does anyone have any insight on this?
Thanks
In fact, the parameter type does need to be qualified (unless your example is incorrect and you intend for Process to be a member function of Some).
Assuming the following snippet:
class Some
{
public:
struct Crap{};
Crap Process(Crap&);
};
Some::Crap Some::Process(Crap& crap) { ... }
Basically, Crap does not require scoping inside the function parameter list and body for the same reason you don't need this-> to access data members and member functions: it is implicit because it is at the same scope.
The reason return type is needed is simply because the parser encounters the return type before the method name and cannot (is not required to?) deduce scope at that moment.
The question title says 'member function', but your example contains no member function. Assuming you meant Some::Process rather than just Process:
The class scope for the member function definition begins at the (, not at the {. I assume the reasoning is exactly so that things like this can be typed shorter.