In c++17 is it possible to do template meta-programming to detect if “this” was part of the capture group some how? Or at runtime?
I have a class A that accepts the lambda for later invocation. However, if the object B owning A captures “this” in the lambda it gives A, then it can cause a subtle use-after free. Being able to crash in this scenario would be valuable.
I’m aware their wouldn’t be 100% (eg a user could capture it as “a = this” or “b = (void*)this”). I also don’t expect to be able to capture all problems (eg if I capture a reference to a member variable). I’m just looking to add some confidence in the obviously wrong scenarios
A lambda is nothing more than a class generated by the compiler that has an overloaded operator(). There is no mechanism in template programming that can (cross-platform) detect if a particular type was generated by the compiler, let alone introspect into the "members" of that class to figure out what it captured and how.
You will simply have to expect users of your system to exercise proper discipline.
I understand that when an ellipsis (...) occurs to the right of a pattern containing a parameter pack, the pattern is expanded once for each parameter in the pack. However, though I have been able to find isolated examples of patterns with their expansion, I have been unable to find a definition of what constitutes a pattern. From what I can see, whitespace plays no role in the definition of the pattern, but parentheses do. For instance, in this example:
template<typename ... Ts>
void func(Ts)
{
do_something(validate(Ts)...);
}
the do_something line would be expanded to:
do_something(validate(var1), validate(var2), validate(var3))
if Ts happened to represent three variables. By contrast:
do_something(validate(Ts...));
would be expanded to:
do_something(validate(var1, var2, var3));
So clearly parentheses have something to do with determining where the pattern begins and ends. I can also see that whitespace does not. But that only gets me so far. I'd like to know exactly what constitutes a pattern, and how it will be expanded. I tried searching through the C++ Standard, but found too many instances of "parameter pack" to make that effective. Could someone please give me a definition of "pattern", or a link to a definition, or both?
UPDATE: To limit the scope of my question, I'd like to focus on the case where a pattern occurs within a function call. I've edited the title accordingly. Sorry I didn't make that clear from the beginning.
A pattern is defined in the standard under [temp.variadic]/4: (via #t.c.)
A pack expansion consists of a pattern and an ellipsis, the instantiation of which produces zero or more instantiations of the pattern in a list (described below). The form of the pattern depends on the context in which the expansion occurs. Pack expansions can occur in the following contexts:
In a function parameter pack ([dcl.fct]); the pattern is the parameter-declaration without the ellipsis.
In a template parameter pack that is a pack expansion ([temp.param]):
if the template parameter pack is a parameter-declaration; the pattern is the parameter-declaration without the ellipsis;
if the template parameter pack is a type-parameter with a template-parameter-list; the pattern is the corresponding type-parameter without the ellipsis.
In an initializer-list ([dcl.init]); the pattern is an initializer-clause.
In a base-specifier-list (Clause [class.derived]; the pattern is a base-specifier.
In a mem-initializer-list ([class.base.init]) for a mem-initializer whose mem-initializer-id denotes a base class; the pattern is the mem-initializer.
In a template-argument-list ([temp.arg]); the pattern is a template-argument.
In a dynamic-exception-specification ([except.spec]); the pattern is a type-id.
In an attribute-list ([dcl.attr.grammar]); the pattern is an attribute.
In an alignment-specifier ([dcl.align]); the pattern is the alignment-specifier without the ellipsis.
In a capture-list ([expr.prim.lambda]); the pattern is a capture.
In a sizeof... expression ([expr.sizeof]); the pattern is an identifier.
In a fold-expression ([expr.prim.fold]); the pattern is the cast-expression that contains an unexpanded parameter pack.
The above quote from the standard draft talks about what part of the grammar described in the links is the "pattern" that is being expanded. To understand it, you need to know how the C++ grammar is described and the exceptions about how it is used in the standard text itself; however, if you have basic BNF knowledge and a bit of patience, you can work it out. The names are often useful as well.
However, you can use ... and mostly understand it without going nearly that deep.
The general rule is simple: you have some bit of C++ grammar (called the pattern) parsed in the usual way, where a pack of types is treated like a single type, and a pack of literals is treated like a single literal. Then, at the end of it, you have a ... expander. It then takes all of the unexpanded packs in the bit of C++ grammar immediately before (the pattern) and expands it.
How this works in each context is different; it isn't just a macro expansion. The contexts in which ... is valid are enumerated above; the effects of the expansion are listed in the standard at each point where it is valid.
In the most mundane use cases of ..., the pattern is an expression, and the expression gets expanded as-if it was each copy separated by , (not operator,, but the other "normal" one), usually in a context where a list of things is expected (function call, initializer list, etc).
There are function parameter declaration contexts (where ... both expands the types of the function parameters, and introduces a new pack of the paramter names), in template parameter lists (where it introduces a pack usually), etc.
sizeof... is a bit strange: for sizeof... it counts how many elements are in the pack passed in the (). This works differently, as the ... does not apply to the "structure on the left".
For alignas(X...), we end up with alignas(X#0), alignas(X#1), ... (where #0 is my pseudocode for the first element of the pack), as alignas(X#0, X#1, ...) is not valid C++ (again #T.C. in comments below).
For inheritance, it creates a set of base classes. For mem-initializer-lists, it lets you pass ctor arguments to said pack of base classes. For lambdas, it gives you limited capture of packs (not full on expression capture with expansion last I checked).
The pattern is the thing expanded. Importantly, an expanded pattern is not expanded by another pattern expander: so std::array< Ts, sizeof...(Ts) >... is a pack of arrays of various types, each one with a number of elements determined by how big the pack itself is. sizeof...(Ts) "counts as expanding" the Ts in its (), even though ... isn't to "its right", because the language defines the Ts in the () as the pattern that is expanded by the ....
The pattern in the general case cannot be called an expression, because types are not expressions, and some patterns are expressions (or at least expand into lists of expressions). And in some cases, ... expands a type-pattern into an expanded package of types (like in the throw expression).
The general rule, that you treat ... as expanding the thing on the left in an appropriate way in the local context, works for almost everything except sizeof... (which is a magical operator that tells you how many elements are in a parameter pack). It is only going to be in corner cases where this doesn't produce a decent model. And in my experience, at worse it will result in code that doesn't compile when you think it should; you can learn workarounds in that case. Like, remembering that a bare statement "has no local context", so you cannot do a = std::get<Is>(tup))...;, but rather the workaround (void)(int[]){0,(a = std::get<Is>(tup)),0)...}; (might have to typedef that int[]) where we provide a context (creating an array) for the pack expansion to work in.
C++1z's fold expressions are another quirky spot where ... does not apply on the left; here, they wanted to have an expansion of a binary operator, so "on the left" doesn't make as much sense as the usual "unary" expansion.
The pattern is defined by its association with the ... expansion syntax. So validate(ts) alone is just a fragment of meaningless text. But validate(ts)... makes the validate(ts) part the pattern of the expansion. So it's a matter of how ... affects the associated code.
Usually, unpack syntax designates that the stuff to the left of the ... is the pattern. With C++17's fold expressions, this becomes a bit more complex. But generally speaking, if you want to know what the pattern is, find the ..., and look at the expression immediately to the left of it.
The specific limitations on what can be in the pattern depend entirely on where the expansion is taking place and what kind it of pack is involved (type vs. non-type, etc). The pattern needs to be whatever would be legal code for whatever context it is expanded within.
Azure WebJobs are so simplify to work with parameter binding, so sometimes it is hard to guess which parameter goes from and to.
For example, ProcessQueueMessage([QueueTrigger("webjobsqueue")] MyClass input, string Name, [Blob("container/{Name}", FileAccess.Write)] Stream writer) shows that Name is given from a property in MyClass which is automatically converted from Json string type.
I just copy and use some sense from examples but I don't have concrete knowledge why Name is there and how it is binded with previous MyClass parameter without any words.
I read several links from here and there and even examples, but I want to read whole description of parameter binding rules. Could you provide a well-documented receipe or cheatsheet about this?
There is one cheatsheet (from 2014, so it might be the forthcoming one mentioned in the comments) at http://download.microsoft.com/download/2/2/0/220DE2F1-8AB3-474D-8F8B-C998F7C56B5D/Azure%20WebJobs%20SDK%20Cheat%20Sheet%202014.pdf
Can I get the string with regular expression from std::regex? Or should I save it somewhere else if I want to use it later?
In boost you can do this:
boost::regex reg("pattern");
string p = reg.str();
or use << operator
cout << reg; will print pattern.
but in std::regex there is no str() or operator<<. Should I save my string somewhere else or I just can't find it?
In debugger I can see what's in std::regex.
I just looked in N3225, section 28.4 (header <regex> synopsis) and indeed, the basic_regex template has no member function str, and there are no operator<< provided.
The paragraph 28.8/2 provides a little insight on this :
Objects of type specialization of
basic_regex are responsible for
converting the sequence of charT
objects to an internal representation.
It is not specified what form this
representation takes, nor how it is
accessed by algorithms that operate on
regular expressions.
What I understand is that the standard mandates that basic_regex can be constructed from const charT * but does not require the implementation to keep this string.
The MSDN docs seem to show that there's no publicly accessible way to retrieve the regex pattern from a constructed object, so I would say that you need to save the string yourself.
In order to keep a regular expression more brief, is there a shorthand way to refer to a character class that occurs earlier in the same regular expression?
Example
Is there a way to shorten the following:
[acegikmoqstz##&].*[acegikmoqstz##&].*[acegikmoqstz##&]
Keep in mind that regex features are dependant on the language being used.
With Java, you can do this:
[acegikmoqstz##&](?:.*[acegikmoqstz##&]){2}
But that's all, with java you can't refer to named subpattern.
With PHP you can do that:
(?(DEFINE)(?<a>[acegikmoqstz##&]))\g<a>(?:.*\g<a>){2}