In boost spirit there are parantheses which can be used to indicate that a part of grammar is going to be repeated
A>>(B>>C)*
I want to use this concept to write a generic scenario controller but I have no idea how they implemented that the parantheses are implicitly creating some object around B and C
Well, it seems you're asking about the attributes of rules. Spirit can propagate the parsed content automatically to data types. Each parser, also *(...), defines rules how those data types should look like. You'll find it as "attribute propagation" in the documantation.
Here are two interesting links for this subject:
http://boost-spirit.com/home/articles/attribute_handling/attribute-propagation-and-attribute-compatibility/
http://www.boost.org/doc/libs/1_55_0/libs/spirit/doc/html/spirit/abstracts/attributes.html
Related
Combining if constexpr with some <type_traits> entities, in C++17, I'm able to inspect types at compile time. Can these techniques be considered static reflection? Or is it just type inspection? Example:
if constexpr (std::is_same_v<T, U>) statement
Does the reflection concept apply only to runtime? Is right to call it static reflection?
Could is_same be considered a form of static reflection? It is in fact static, a compile-time detectable property of a type. And you can in fact write code that will execute based on introspecting this property. So technically, it is perfectly valid to call it "reflection".
But if you're going to be useful with words, if you want to effectively use words to communicate, then you have to recognize that dictionary definitions aren't exactly useful. This is because people have different dictionaries, different expectations of what words mean. And words can change their meaning or have special meaning in different contexts. So if you're going to effectively communicate with people, you have to use words that will actually convey the meaning that you intend to communicate.
In particular, the words "static reflection" in the context of C++ typically refer to functionality related to this proposal (PDF) (cleverly named "Static Reflection") and its many, many revisions. Specifically, if you make the claim that C++ has "static reflection" as some kind of language feature, then to many C++ users, you are making the claim that users can do things like enumerate properties about a class (like the member subobjects of a type) and iterate over them, performing some action on each such property.
After all, that is what you can do in other languages that offer reflection as a first-class feature. "Reflection" is not just being able to ask if a given type is a particular type or if a given type satisfies a basic property. Reflection is about being able to introspect pretty much every facet of interest on a type.
That's the expectation that the term "static reflection" gives many C++ programmers. When C++ programmers talk about wanting "static reflection", that is what they're saying that they want.
So while you could technically claim that C++ already has "static reflection", it is not useful to make such a claim.
I would say that yes, the basic idea that reflection can be done at compile time (giving static reflection) is entirely reasonable. In fact, there have been a number of papers about static reflection in C++ for a while now. For one obvious example, consider N3996: Static Reflection.
In fact, the C++ Committee has an official Study Group (SG 7), which now covers compile-time programming in general, but was originally dedicated to static reflection.
Now as to whether static if with some type traits qualifies as static reflection, I'd say the answer is "yes", but with some pretty heavy qualifications, or at least limitations. For example, static if with type traits probably isn't sufficient to implement any of the motivating examples shown in the paper linked above.
Nonetheless, it does allow some minimal degree of reflection, and it'd done at compile time, so it clearly is static reflection.
Ive spent the day reading notes and watching a video on boost::fusion and I really don't get some aspects to it.
Take for example, the boost::fusion::has_key<S> function. What is the purpose of having this in boost::fusion? Is the idea that we just try and move as much programming as possible to happen at compile-time? So pretty much any boost::fusion function is the same as the run-time version, except it now evaluates at compile time? (and we assume doing more at compile-time is good?).
Related to boost::fusion, i'm also a bit confused why metafunctions always return types. Why is this?
Another way to look at boost::fusion is to think of it as "poor man introspection" library. The original motivation for boost::fusion comes from the direction of boost::spirit parser/generator framework, in particular the need to support what is called "parser attributes".
Imagine, you've got a CSV string to parse:
aaaa, 1.1
The type, this string parses into, can be described as "tuple of string and double". We can define such tuples in "plain" C++, either with old school structs (struct { string a; double b; } or newer tuple<string, double>). The only thing we miss is some sort of adapter, which will allow to pass tuples (and some other types) of arbitrary composition to a unified parser interface and expect it to make sense of it without passing any out of band information (such as string parsing templates used by scanf).
That's where boost::fusion comes into play. The most straightforward way to construct a "fusion sequence" is to adapt a normal struct:
struct a {
string s;
double d;
};
BOOST_FUSION_ADAPT_STRUCT(a, (string, s)(double, d))
The "ADAPT_STRUCT" macro adds the necessary information for parser framework (in this example) to be able to "iterate" over members of struct a to the tune of the following questions:
I just parsed a string. Can I assign it to first member of struct a?
I just parsed a double. Can I assign it to second member of struct a?
Are there any other members in struct a or should I stop parsing?
Obviously, this basic example can be further extended (and boost::fusion supplies the capability) to address much more complex cases:
Variants - let's say parser can encounter either sting or double and wants to assign it to the right member of struct a. BOOST_FUSION_ADAPT_ASSOC_STRUCT comes to the rescue (now our parser can ask questions like "which member of struct a is of type double?").
Transformations - our parser can be designed to accept certain types as parameters but the rest of the programs had changed quite a bit. Yet, fusion metafunctions can be conveniently used to adapt new types to old realities (or vice versa).
The rest of boost::fusion functionality naturally follows from the above basics. fusion really shines when there's a need for conversion (in either direction) of "loose IO data" to strongly typed/structured data C++ programs operate upon (if efficiency is of concern). It is the enabling factor behind spirit::qi and spirit::karma being such an efficient (probably the fastest) I/O frameworks .
Fusion is there as a bridge between compile-time and run-time containers and algorithms. You may or may not want to move some of your processing to compile-time, but if you do want to then Fusion might help. I don't think it has a specific manifesto to move as much as possible to compile-time, although I may be wrong.
Meta-functions return types because template meta-programming wasn't invented on purpose. It was discovered more-or-less by accident that C++ templates can be used as a compile-time programming language. A meta-function is a mapping from template arguments to instantiations of a template. As of C++03 there were are two kinds of template (class- and function-), therefore a meta-function has to "return" either a class or a function. Classes are more useful than functions, since you can put values etc. in their static data members.
C++11 adds another kind of template (for typedefs), but that is kind of irrelevant to meta-programming. More importantly for compile-time programming, C++11 adds constexpr functions. They're properly designed for the purpose and they return values just like normal functions. Of course, their input is not a type, so they can't be mappings from types to something else in the way that templates can. So in that sense they lack the "meta-" part of meta-programming. They're "just" compile-time evaluation of normal C++ functions, not meta-functions.
From what I understand, standard layout allows three things:
Empty base class optimization
Backwards compatibility with C with certain pointer casts
Use of offsetof
Now, included in the library is the is_standard_layout predicate metafunction, but I can't see much use for it in generic code as those C features I listed above seem extremely rare to need checking in generic code. The only thing I can think of is using it inside static_assert, but that is only to make code more robust and isn't required.
How is is_standard_layout useful? Are there any things which would be impossible without it, thus requiring it in the standard library?
General response
It is a way of validating assumptions. You wouldn't want to write code that assumes standard layout if that wasn't the case.
C++11 provides a bunch of utilities like this. They are particularly valuable for writing generic code (templates) where you would otherwise have to trust the client code to not make any mistakes.
Notes specific to is_standard_layout
It looks to me like the (pseudo code) definition of is_pod would roughly be...
// note: applied recursively to all members
bool is_pod(T) { return is_standard_layout(T) && is_trivial(T); }
So, you need to know is_standard_layout in order to implement is_pod. Given that, we might as well expose is_standard_layout as a tool available to library developers. Also of note: if you have a use-case for is_pod, you might want to consider the possibility that is_standard_layout might actually be a better (more accurate) choice in that case, since POD is essentially a subset of standard layout.
I get the feeling that they added every conceivable variant of type evaluation, regardless of any obvious value, just in case someone might encounter a need sometime before the next standard comes out. I doubt if piling on these "extra" type properties adds a significant additional burden to compiler developers.
There is a nice discussion of standard layout here: Why is C++11's POD "standard layout" definition the way it is?
There is also a lot of good detail at cppreference.com: Non-static data members
I want to recognize all of my servers over my office network. They have a particular naming pattern which only I use. I've defined it in a simpleType.
Now I was told I have to filter my servers from a list of full DNS names (like www.bla.moo.oneofmyservers.foo.loo). My naming strategy has a length limit. I would have simply put it inside a *mystrategy* if not for that.
Is there a way to reference my type from within a pattern definition?
It didn't work when I wrote *mytype*.
Assuming that what you're asking is something like this:
I have a pattern and I've used it as a constraining facet in a simple type; now, I want to make another type, and for maintenance purposes, I wish to somehow reference that pattern, so that I don't have to maintain it in two different places...
The answer is no, you can't. Constraining facets in XSD are not referenceable entities; nor types are referenceable within constraining facets.
On Page 175 Paragraph 1 of Effective C++ Meyers has this to say about generalized functors and binding:
I find what tr1::function lets you do
so amazing, it makes me tingle all
over. If you're not tingling , it may
be because you're staring at the
definition of ... and wondering what's
going on with the ....
And I agree with him on bind and function. About lambda, Well I understand what lambda does and how it does it, but could someone post a book style mind-blowing snippet or a verbal outline of why lambda is supposed to (in Meyers' terminology) blow my socks off ? I ask because each area of C++ where the placeholder syntax is used seems like a hack to me (yes, I know enough about the functional method, so please no basics), I agree with the way it's used in bind and MPL; However, in the case of lambda I just want it justified so I can decide weather I should enter it into my repertoire.
-- edit --
This SO answer mentions the inlined creation of a functor using just placedholder syntax, he mentions advanced usage, and this is probably what I am after... in advanced usage is it still just inlined creation of functors ?
Based on the comments left above, and the link in the question, the following is the answer I accept (community wiki) :
Boost.Lambda fills the purpose of inline functor creation (that's the term I like). This functionality can be filled by Function + Bind, but it is more verbose than it needs to be, and for simple functors this is unnecessary — e.g., the sort shown in the comments above.
There is obviously semantic overlap between the Function-Bind pair and Lambda — this is a historical artifact, and because Lambda has its raison d'être, it exists in Boost.
What is "cool" about it is that, as with boost foreach and boost parameter, injects/extends syntax into C++ which is not in the language, ie it emulates anonymous functions directly as parameters.