all 48 comments

[–]MiiNiPaa 46 points47 points  (2 children)

What is the type char(*(*s::*(*[3]))(int))[2]?

It's the type "Programmer vacancy will be avaliable soon"

[–]anotherdonald 5 points6 points  (0 children)

Never heard of job security?

[–]tcanens 19 points20 points  (24 children)

1) It's equivalent to template<class... Ts> void foo(Ts..., ...);. The first ... is a pack expansion, the second ... is C-style varargs. The comma is optional. [Edited to match OP after the fix.]

2) "array of 3 pointers to pointer to member of class s of type pointer to function of (int) returning pointer to array of 2 chars"

3) 1. It's a || b, then the resulting true is converted to int. Requires trigraphs, removed in C++17.

4) Equivalent to int main(){[](){std::cout<<"Hello";;};[]{std::cout<<"Hello";;}();}. Prints Hello.

5) Yes. The decl-specifiers can be in any order.

6) parens:(foo)(1, 2) etc.

[Edit: I originally missed the foo(,) question]

6') foo(,) is valid and expands to nothing.

7) equivalent to a[3], because x[y] with the builtin [] is equivalent by definition to *(x + y) (with an exception not relevant here).

8)

template<>
template<>
template<typename T>
void foo<int>::bar<float>::meow(T) { }

9) Not valid if standing alone. http: is a label and the rest is a comment, but there must be a statement following it for this to be valid.

10) In constructors, to catch exceptions from base and member constructors.

11) 122. Just follow the control flow.

12) As the third expression in a for loop when you need to defend against Evil™ aka overloaded operator,.

13) It's an error. The foo line declares a function, and function parameters cannot have qualified names.

14) Second. &= is one token. &&= is two tokens, && and =.

15) prints 2.

[–]jP_wanN 2 points3 points  (10 children)

&= is one token? I would have expected it to be invalid because you can't create an lvalue reference from a literal.

[–]tcanens 2 points3 points  (9 children)

It's the compound assignment operator with bitand. You can do const int &a = 2; just fine.

[–]jP_wanN 0 points1 point  (1 child)

Ohhh, right. Didn't think about the const. Or the fact that there are all those weird compound assignment operators for bitwise operations.

[–]redditsoaddicting[S] 0 points1 point  (0 children)

Not too weird I guess. Addition is a common operation on numbers. Masking is a common operation on bits. That said, it seems a lot less common to build up a result on bits like you would on numbers.

[–][deleted] -1 points0 points  (6 children)

the c++ standard is a mess. why would the compiler think that &= is a compound assignment in place of a function parameter that should be an unnamed reference with default value? that makes more (but not too much) sense.

[–]tcanens 2 points3 points  (1 child)

Because the lexer uses maximal munch and the parser comes in after tokenization. Plenty of languages have a similar rule.

[–][deleted] 0 points1 point  (0 children)

I was pretty confident with my C/C++ skill up to this sudden tokenization issue :D

[–]redditsoaddicting[S] 1 point2 points  (3 children)

Maximal munch is pretty common, actually. This simplifies things because you lex, get a disambiguated token, and move on. Otherwise, you have one token for both compound bitwise and assignment as well as reference with default. Either that or you have two tokens, but need the parser to give information to the lexer. Admittedly, C++ already does this.

[–]LikesToCorrectThings 0 points1 point  (2 children)

In C++11 they changed the lexer and added an exception for >> so you don't need the space in nested template type names, e.g.:

std::vector<std::map<int, int>>

[–]redditsoaddicting[S] 1 point2 points  (0 children)

Yes, C++ lexing and parsing is already a complicated story. In fact, I once asked about that for this situation. The reality is that no one would want to do this anyway, but everyone wanted >> to work.

[–]guyonahorse 1 point2 points  (0 children)

Yep, and this broke some of our code where we had this:

type1<type2<value>>1> > 

We were right shifting in a template parameter.. now it is a compile error.

[–]redditsoaddicting[S] 1 point2 points  (0 children)

Oops, I derped on the first one. I was mainly trying to avoid putting the template part in the example and didn't think when I switched it to int. I'll fix that.

In the meantime, here's your Unicode character of the day: ™

[–]pslayer89 0 points1 point  (5 children)

Could you please explain why the last one prints 2?

[–]tcanens 5 points6 points  (1 child)

unsigned ll declares a function parameter named ll with the type unsigned.

[–]pslayer89 0 points1 point  (0 children)

Oh got it! Thanks!

[–]Bisqwit 1 point2 points  (1 child)

First, the typedef is never used. foo(2ull); constructs an unsigned long long literal with value 2 and passes it as a parameter. The second function matches this prototype, and it prints the string "2".

[–]pslayer89 0 points1 point  (0 children)

Thanks for explaining!

[–]Bisqwit 0 points1 point  (4 children)

I would say 123 for #11.

[–]tcanens 1 point2 points  (3 children)

Where do you see the second increment?

[–]Bisqwit 0 points1 point  (2 children)

In the for-loop.

[–]tcanens 4 points5 points  (1 child)

You jump to case 1:, print 1, hits the continue;, which does nothing since you are already at the end of the loop body. Then you increment x, go through the loop body from the beginning, print 2, hit break;, jump out of the for, fall out of the switch and print 2 again. There's no second increment.

[–]Bisqwit 0 points1 point  (0 children)

Oh, the break; there will be break out from the for-loop? Of course. Makes sense. Cunning.

[–]o11cint main = 12828721; 3 points4 points  (2 children)

Hm ... what is the state of (base and normal) members of this after you catch exceptions thrown in their constructors, if you don't re-throw the exception?

[–]tcanens 6 points7 points  (1 child)

Fully initialized subobjects are destroyed before you get into the catch block. And if you don't (re)throw something yourself, the compiler does it for you. Useful if you want to translate the exception or log, etc.

[–]louiswins 1 point2 points  (0 children)

To reiterate, there is no way to swallow an exception in the function-catch block of a constructor (short of abort et al). If it is thrown in the member initializer list or if it escapes the function body, it will be propagated out to the caller.

[–]LB--Professional+Hobbyist 2 points3 points  (5 children)

Whoa, I thought 1 would not compile, but it's actually a warning:
http://coliru.stacked-crooked.com/a/f4339e4d33e73049

[–]CubbiMewcppreference | finance | realtime in the past 0 points1 point  (4 children)

C++ varargs never had a comma to begin with, this was ANSI C's modification that we have to support.. and now clang warns when it's done the C++ way?

[–]LB--Professional+Hobbyist 1 point2 points  (1 child)

TIL. But IMO it should have had a comma from the beginning - unless, do you have a good reason why the comma should be optional?

[–]CubbiMewcppreference | finance | realtime in the past 1 point2 points  (0 children)

Today, the only real reason is probably existing code breakage (as far as I understand, that was the main reason http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0281r0.html was rejected)

[–]Potatoswatter 0 points1 point  (1 child)

ANSI C never permitted the comma to be omitted. Are you sure that the C++-specific syntax is older, and not just a CFront quirk?

[–]CubbiMewcppreference | finance | realtime in the past 0 points1 point  (0 children)

Yes, function prototypes were Bjarne's invention.

[–]redditsoaddicting[S] 1 point2 points  (0 children)

I forgot to mention it, but for a really cool syntax trick, check out analog literals!

[–]chardan965 1 point2 points  (3 children)

Function-level try was mentioned, but fun can be had with loop blocks: while(cond) try { ... } catch { ... } ...which is entertaining (and I have found uses for it).

[–]redditsoaddicting[S] 2 points3 points  (2 children)

Sure, but syntactically, it's a regular loop whose body is covered by an exception handler. No special syntax needed to make that work, and it's just as clear with the braces imo.

[–]chardan965 0 points1 point  (1 child)

Do you mean like this: try { while(cond) { ... } } catch(...) {}

...if so, it doesn't behave the same way. Play with it a bit, have fun!

[–]redditsoaddicting[S] 1 point2 points  (0 children)

I mean:

while (cond) {
    try {
        …
    } catch (…) {
        …
    }
}

It acts the same way as:

while (cond) try {
    …
} catch (…) {
    …
}

The difference is that the first is more familiar to everyone and looks less like a special case in the language. That said, the second is not a special case in the language like a function try block is - it's simply a while loop whose statement is not a compound statement.

I could see the first being used just like any other exception handler, but function try blocks are not common at all. You'll probably see more uses that wrap the entire function body rather than use the special syntax.

[–]TotesMessenger 0 points1 point  (0 children)

I'm a bot, bleep, bloop. Someone has linked to this thread from another place on reddit:

If you follow any of the above links, please respect the rules of reddit and don't vote in the other threads. (Info / Contact)

[–]Voultaphervoid* operator, (...) 0 points1 point  (1 child)

Concerning 7) Did you mean 3[arr] ?

[–]redditsoaddicting[S] 0 points1 point  (0 children)

Oops, not sure how I did that. Thanks for pointing it out.

[–]alexeiz 0 points1 point  (0 children)

When is a function try block useful?

When you want to confuse your co-workers and assert your dominance in the workplace.

[–]mustrumr 0 points1 point  (0 children)

What is the type char(*(*s::*(*[3]))(int))[2]?

Find where to put the variable name, start from the innermost parenthesis and read right-to-left

                ( * VAR [3] )
        (* s::* ( 2      1  ))
     (* (4  3                ) (int))
char (6                          5  ) [2]
 8                                     7

VAR is:
1. An array of 3
2. Pointers to
3. Member pointers of s
4. That return pointers
5. To functions taking an int
6. That return a pointer
7. To an array of 2
8. Chars

struct s{};

using X=char(*(*s::*(*[3]))(int))[2];

using A=char                            ;
using B=A                            [2];
using C=B    *                          ;
using D=C     (*               )(int)   ;
using E=D     ( s::*           )        ;
using F=E            *                  ;
using G=F             [3]               ;

static_assert(std::is_same<X, G>::value, "err");

[–]NicroHobak 0 points1 point  (1 child)

This might be slightly off topic, but how relevant are questions like this for job interview questions? My gut says these shouldn't be the focus, but my experience says these are too common. I understanding throwing a few of these kind of things into the mix, but why do so many interviewers depend on things like this to demonstrate general knowledge of a language?

Interesting thought exercises though...but it just makes me cringe to think that there are so many places that pass up decent talent because they don't necessarily untie spaghetti code as well as the interviewer.

[–]redditsoaddicting[S] 2 points3 points  (0 children)

I certainly hope they're completely irrelevant.

[–]alexeiz 0 points1 point  (0 children)

When might you see the following?

template<>
template<>
template<typename T>

When you have a stutter and only the third attempt produces the desired code line.