C++ Programming Interviews: What Interviewers Want You To Show

C++ Programming Interviews: What Interviewers Want You To Show

  • Comments 35

A recent study showed that C++ is still among the most used languages (ahead of any other Visual Studio officially supported language like C# or Visual Basic). But despite being widely used and known by several generations of developers –thanks that it has been out there for decades now, while being still the most taught language in the Academy- when you look for a C++ development job those facts don’t guarantee that you’ll be chosen. It will depend on how well you perform in the programming interview –among other factors. Regardless of how deeply you know the C++ syntax, how many STL components you memorize, it will be your abilities of using “the right tool for the right task” what will define your eligibility. This post will seem like a lost chapter of the book Programming Interviews Exposed-Secrets to Landing Your Next Job, 2nd Edition [Mongan, Soujanen, Giguère; Wrox 2007], but it’s based on reflections I can share from a programming interview I participated. While this post is initially intended for candidates who are to be interviewed, it feels like a novice programming interviewer may get some ideas from here about what to check on a candidate.

 

In an interview, I was asked to pseudo-code a function that returns the decimal equivalent of a roman numeral received as input. It seems like a trivial challenge but what the aspiring candidate must keep in mind, first of all, is the fact that the interviewer isn’t curious about your background with roman numerals. What he/she wants to check are your abilities in problem solving. Beside, the roman numeric system isn’t that trivial compared with the decimal system. It’s non-positional (in the sense that you don’t get ones in the last position, tens in the penultimate, hundreds in the position before, etc.). Beside, the system only contains symbols to represent powers of 10 (10n, n=0, …,3) and 5x10n (n=0, …,2). Bizarre enough, huh? I wonder if the romans created this numeral system in order to later use it in programming interviews.

Regarding those unusual features, the first thing I started doing –in front of my interviewer and with the whiteboard marker in my hand- was an exploration of typical equivalences, easy and not so easy roman numeral cases with their expected result. Those served me to both, craft the algorithm toward the general case and test my derived solution for correctness.

Some positive cases

Those and some few other examples help us determine some basic syntax rules in roman numerals. Rules like repetition of characters (III, CC, XXX, …); subtraction (IX, CD, …); etc.

Those same rules have their own limitations, for instance

Wrong cases

In other words, repetition is only allowed to characters I, X, C and M (1, 10, 100 and 1000 respectively) but not to V, L, D (5, 50, 500 respectively) and -while not represented in these examples- it can’t happen more than three times either. Subtracting V, L or D isn’t allowed either. Likewise, the 3rd erroneous example shows that we can get a character subtracting its immediate follower, but this latter can’t subtract to a third one (that is to say, a subtracting portion in a whole roman numeral only involves two characters).

Talk about all these rules, exceptions and thoughts like thinking in loud voice, as you write them down in some margin (whiteboard in my case but it could be a piece of paper you were given). If available, use two different colors to separate DO’s and DON’T’s.

DO's and DONT's

There are yet other syntax rules but, with my interviewer, we agreed to stop here as was good enough to show some skills in the remaining time.

Let’s start shaping the function skeleton, its public interface and expected return types

  1. namespace RomanNumeral {
  2.     unsigned int rtoi(const basic_string<Ch>& romanStr);
  3.     ...
  4. }

The function name, rtoi(), was chosen for its similarity in intention with atoi(). There are several decisions to explain here:

  • The returned type was chosen as unsigned int. Roman numerals don’t consider neither 0 (zero) nor negative numbers. For that reason, I wanted to make sure that the returned type were as restrictive as possible.
    It may be argued that by allowing all kind of int, we could have taken the convention of using negative numbers to represent errors like invalid inputs, etc. But the drawback of that approach is that the caller of the function will have to take the precaution of explicitly asking for error conditions coming as output. If the caller fails to check this out and just used the result instead, the execution would turn into an undetermined state.
    That’s why I preferred to escalate an error. We recently debated about exceptions and while there’s no one-size-fits-all solution for it, I liked to declare my conversion exception as a subclass of STL runtime error:
  1. namespace RomanNumeral {
  2.     ...
  3.     enum ConversionErrorCause {
  4.         IllegalSymbol,        // input contains a symbol other than I, V, X, L, C, D, M
  5.         IllegalRepetition,    // I, X, C, M repeated more than three times, or any other symbol repeated
  6.         IllegalSubtraction    // V, L, D can't subtract
  7.     };
  8.  
  9.     class ConversionError : public std::runtime_error
  10.     {
  11.     private:
  12.         ConversionErrorCause m_Cause;
  13.  
  14.     public:
  15.         ConversionError(ConversionErrorCause);
  16.         ConversionErrorCause cause();
  17.     };
  18.     ...
  19. }

There’s no prescription indicating that your exceptions should inherit from STL runtime_error or any other STL exception, but there’s some consensus that if this practice were widely adopted, you have an alternative to the catch (...) ellipsis that in Windows and non-Windows systems may catch things other than C++ exceptions (beside not telling you exactly what exception occurred, just that something went wrong).
Conversely, some other authors have arguments against throwing exceptions (arguing that it comes at the expense of a runtime overhead among other reasons.) They suggests alternatives like the old C global errno or similar (especially when the function is intended to validate user input). Those authors propose that exception throwing should be a last instance resort when nothing else may be attempted. In my case, this function is just a library function: it may be called by a UI validator object or by another component not necessarily related with user input so I can’t make such assumptions like a human been being in front of the application to attempt a manual recovery, etc. This general purpose function will react to input errors by throwing exceptions. Period.
As you can see in the code sample above, I created a generic exception for any potential cause instead of making a complete exception hierarchy, as long as I still provide through its cause() method (and, when defining this exception, through its std::runtime_error::what() method as well) what specifically failed.
Alright, enough said about exceptions, let’s keep reviewing the function interface.

  • Regarding its input argument, the reader might wonder why to declare it as const. The fact is that this function shouldn’t modify its input in any way. Therefore, is not a bad idea to enforce that so if some day, as a consequence of maintenance, any programmer modified the input declared as constant, the application wouldn’t compile.
  • Another aspect considering the input string is the fact that I chose it as wstring instead of simply string type. The fact is that most systems nowadays work with expanded character sets (typically UNICODE), as they better handle internationalization in currently Internet-enabled, interconnected age. You don’t have to reason like me here, as long as you are able to understand the context where your decisions are being taken. A wrong decision, though, would have been preferring string for simplicity: from a programming perspective, both types are siblings, specializing a common STL type called basic_string (with char and wchar_t, depending on the simple or expanded case). In fact, if the interviewer asked you about a generic solution, that would come as follows:
  1. namespace RomanNumeral {
  2.     template<typename Ch> unsigned int rtoi(const basic_string<Ch>& romanStr);
  3.     ...
  4. }

Yet one may argue about the decision of using the STL version of strings instead of the C-style, 0 (zero)-terminated char arrays. The decision in favor of the STL ones was based on the fact that they encapsulate a lot of the functionality a string must accomplish in order to be considered safe. For instance, a wchar_t* counterpart of our wstring could have come without the expected binary 0 (zero) ending char, leading to a potential buffer overrun. An STL-based string doesn’t have this problem because it handles its own memory (first reason), and its length isn’t based on a potentially missed ending flag. STL strings are safer than their C-style counterparts, what doesn’t mean they are safe. They are just less error-prone and therefore recommended by several authors. They may impose certain overhead but in most of cases that overhead won’t be absent in high quality, defensive-coding version using C-style strings. It’s just a matter of deciding whether you programmer want to be responsible for that overhead or take advantage of those already baked versions that the STL put available for you.

  • A last comment, prior to move inside the function definition itself, is the fact that the string argument is passed as a reference (by adding the ampersand modifier). It’s a matter of efficiency: if the ampersand was not present, the string would be passed by value, being copied to the stack with the consequent overhead. I’d rather avoid that.

All these said, let’s go through the function definition. I’ll finally implement here a generic version (now that I’ve mentioned that possibility)

  1. template<typename Ch> unsigned int rtoi(const basic_string<Ch>& romanStr) {
  2.     int result = 0;                /* value to return */
  3.     AdditiveTerm currentTerm;
  4.  
  5.     unsigned int repeatedTimes;
  6.     
  7.     Ch lastSymbol = L'\0', currentSymbol, nextSymbol;
  8.  
  9.     /* main computing loop: inside reasonable length and without reaching the
  10.        end of the null terminated string */
  11.     for (typename basic_string<Ch>::const_iterator iter = romanStr.begin(),
  12.             iterNext;
  13.             iter!=romanStr.end();
  14.             iter+= currentTerm.size,
  15.             result+= currentTerm.value) {
  16.         currentSymbol = *iter;
  17.  
  18.         /* Rule 1: Repetition. Can't happen more than three times and not every
  19.            symbol is repeatable */
  20.         if (lastSymbol==currentSymbol) {
  21.             if ((++repeatedTimes==4)||(isNotRepeatable(currentSymbol))) {
  22.                 throw ConversionError(IllegalRepetition);
  23.             }
  24.         } else {
  25.             repeatedTimes = 1;
  26.             lastSymbol = currentSymbol;
  27.         }
  28.  
  29.         /* the current symbol plus its follower (if not at the end) are
  30.            evaluated in getNexAdditive() to see how much to cumulate*/
  31.         nextSymbol = ((iterNext = iter+1)==romanStr.end()) ? L'0' : *(iterNext);
  32.         currentTerm = getNextTerm(currentSymbol, nextSymbol);
  33.     }
  34.  
  35.     return result;
  36. }

In few words, this function consists in a loop through all the input string chars. For each char we check whether it repeats or not the last one (in case it does, we control that repeated chars don’t reach 4 times). We also make sure that not every symbol is allowed to be repeated by calling the inline function isNotRepeatable(…) –defined as follow:

  1. template<typename Ch> inline bool isNotRepeatable(Ch c) {
  2.     return ((c==L'V')||(c==L'L')||(c==L'D'));
  3. }

By making it inline, we are instructing the compiler to avoid making any explicit call involving the stack. Instead this code will be spanned in the calling method, making the proper variable substitution. We could have defined a macro this way

  1. #defineisNotRepeatable(c)    (((c)==L'V')||((c)==L'L')||((c)==L'D'))

but in that case we have less control on data being passed/received. An inline function is a better practice and presumably won’t involve the overhead of a true function call.

The iteration then locates the symbol next to the one being analyzed in the current iteration, and passes both to the function getNextTerm(…). The purpose of that function, given those two symbols, is to determine whether both should be combined in a subtraction (the typical case of IV, where I is being subtracted from V for instance), or a case like VI, where only the V will be considered for the iteration, discarding the I (which will be picked up by the next iteration).

Thus, the output of this function is a struct defined as follows

  1. typedef struct AdditiveTerm {
  2.     unsigned int value, size;
  3. } AdditiveTerm;

As the reader may see, the value member contains the value to be added to the ongoing result. The size member, instead, will contain either 1 or 2 depending on whether both symbols were considered (as a subtraction) or only the first one while the other was ignored. Those two activities can be seen as the ending portion of the for loop.

Let’s complete the implementation by defining getNextTerm(…) function:

  1. template<class Ch> AdditiveTerm getNextTerm(
  2.         const Ch firstRomanChar, const Ch follower) {
  3.     AdditiveTerm result;
  4.     result.size = 1;    // default size
  5.  
  6.     switch (firstRomanChar) {
  7.     case L'I':
  8.         switch (follower) {
  9.         case L'V':
  10.             /* I (1) subtracting to V (5) results in 4 */
  11.             result.value = 4;
  12.             /* a subtraction involves 2 symbols, so size is 2 */
  13.             result.size = 2;
  14.             break;
  15.         case L'X':
  16.             result.value = 9;
  17.             result.size = 2;
  18.             break;
  19.         case L'L':
  20.         case L'C':
  21.         case L'D':
  22.         case L'M':
  23.             /* a subtractor can't be less than a 10% of its follower
  24.                (i.e.: 99, IC wrong; must be XCIX) */
  25.             throw ConversionError(IllegalSubtraction);
  26.         default:
  27.             result.value = 1;    /* follower ignored */
  28.         };
  29.         break;
  30.     case L'V':
  31.         /* V, L and D aren't subtractor in Roman numerals */
  32.         result.value = 5;
  33.         break;
  34.     case L'X':
  35.         switch (follower) {
  36.         case L'L':
  37.             result.value = 40;
  38.             result.size = 2;
  39.             break;
  40.         case L'C':
  41.             result.value = 90;
  42.             result.size = 2;
  43.             break;
  44.         case L'D':
  45.         case L'M':
  46.             throw ConversionError(IllegalSubtraction);
  47.         default:
  48.             result.value = 10;
  49.         };
  50.         break;
  51.     case L'L':
  52.         result.value = 50;
  53.         break;
  54.     case L'C':
  55.         switch (follower) {
  56.         case L'D':
  57.             result.size = 2;
  58.             result.value = 400;
  59.             break;
  60.         case L'M':
  61.             result.size = 2;
  62.             result.value = 900;
  63.             break;
  64.         default:
  65.             result.value = 100;
  66.         };
  67.         break;
  68.     case L'D':
  69.         result.value = 500;
  70.         break;
  71.     case L'M':
  72.         result.value = 1000;
  73.         break;
  74.     default:
  75.         throw ConversionError(IllegalSymbol);
  76.     }
  77.  
  78.     return result;
  79. }

At a first glance this function could look overwhelming, but the reader will immediately discover that it’s logic is pretty basic and repetitive, despite all the possible cases.

 

Before the interviewer, for completeness, it follows an analysis of the border conditions. For instance, what if the string received as argument is empty (equivalent to “”)? In our case, the function will return 0. It could have also thrown an exception as well, but I’d rather preferred the former option.

We should also test the cases evaluated initially, in order to confirm/tune up the algorithm. I’ve already done it, but I leave those to the reader as an exercise.

From the algorithm itself, it follows a complexity analysis. In that sense, we could conclude that its order is linear to the length of the input. Or, in other words, its complexity is O(n), n being the length of the input, which is pretty much acceptable. Complexities to be avoided whenever possible are quadratic ones –O(n2)- or higher, not to mention exponential ones.

A possible implementation of this function, together with tons of test cases plus an inverse function itor(…) –which takes an integer and returns its roman equivalent- is offered here.

 

Epilogue

There’s a golden lesson to learn regarding programming interviews: do never do more than it was requested, as it may suggest a negative perception about you having difficulties to focus on what’s necessary at a given time. To put an example, I could have solved this test by creating a class called RomanNumeral, with a constructor that receives an input string like the rtoi() function I just defined, so we can later add RomanNumeral objects by redefining the + operator, multiply, etc. as a brand new numeral type. Sounds awesome but… what’s the point in doing so? How likely is, in the real world, that such kind of empowered data type is required? Admittedly, the problem posed in this case is hypothetical but, what’s the reason in answering a hypothetical question by extending the hypothesis beyond its original boundaries?

Bottom line: flying too high while solving a concrete, punctual requirement won’t provoke any other effect than getting your interviewer scared about your abilities to deliver a well-designed solution without falling in the temptation of overarchitecting it unnecessarily, with the potential risk of missing your chance to get the job.

  • > the catch (...) ellipsis that in Windows and non-Windows systems may catch things other than C++ exceptions

    With VC, catch (...) catches Structured Exception Handling exceptions (which are radically different from C++ exceptions) when the compiler option /EHa is used, but not when /EHs or /EHsc are used. For this reason, /EHa should be avoided in favor of /EHs or /EHsc.

    > In fact, if the interviewer asked you about a generic solution, that would come as follows:

    > template<typename Ch> unsigned int rtoi(const basic_string<Ch>& romanStr);

    With that function template alone, rtoi("IV") and rtoi(L"X") won't compile. A possible interview question would be to explain why.

    > By making it inline, we are instructing the compiler to avoid making any explicit call involving the stack.

    The inline keyword is a hint, which the compiler may listen to or may ignore according to its whims. VC's optimizer does listen to the inline keyword to some extent.

    (The inline keyword also activates what I refer to as the Partial ODR Exemption for header-only code.)

    > never do more than it was requested

    Obviously, overengineering is bad. However, asking questions like "Should lowercase be permitted?" is a good thing. Only cyborgs get to say "Because you told me to" as an excuse for interpreting commands literally. Human programmers have to learn how to solve problems at the appropriate level of generality. (Interviews are highly time-constrained, but if I were interviewing someone I would want to see them ask enough questions to define the problem precisely in their head, even if most of the answers are "in the real world, you'd want to handle that, but let's ignore it for today".)

    By the way, here's what it looks like when you throw a real parser at this problem: www.boost.org/.../roman_numerals.html (A real parser is overkill for this toy problem, but in production code the story is very different.)

  • Sadly roman numerals are slightly more complex, because e.g. MIM is a valid number for 1999. None of above implementations seems to handle this.

  • Visual C++ Rocks ! A clue ?

    How is done the kernel from Dave Cutler's Team ? C

    How is done the Windows Applications today ? C/C++ and Managed C++.

    How is done the Windows Explorer ? C/C++ and COM

    How is done the .NET CLR ? C/C++ and COM

    How is done Office main applications ? C/C++ and OLE

    Real Applications are made using C/C++. It should be cool to have a document that lists the Microsoft products and how they are made. => my guess is that C/C++ is 90% more.

    have fun !

    reagrds,

    christophep

  • @Christophe Pichaud:

    Your list is interesting, and I think the majority of the (very successful) projects you mentioned use "classic" C++ (or even pure C, like the kernel), without going crazy with templates or Boost.

    I wrote well-working C++ software, and I've never had to spent brain cycles thinking why template code like this doesn't compile:

     template<typename Ch> unsigned int rtoi(const basic_string<Ch>& romanStr);

    C++ rocks, until it gets rocket-science with templates and template metaprogramming.

  • @Christophe Pichaud:

    They will probably never make such a list for a simple reason: acknowledging that the majority of their products (the same is true for most of the Fortune 500 companies) is written mostly in native C/C++ would be counterproductive because the marketing guys want to promote .net.

    Have a look on Channel9 for example, you will see some (not much) C++ and native code related videos but nothing illustrating how these technologies are used inside Microsoft products nowadays. I also remember some videos where the host is demonstrated some native code world improvements and reacts with comments like "we should no longer use that today, we should use managed code, blah blah blah...".

    Another example would be Microsoft press. The only book available about Windows 7 is an introductory level book (some key components such as Direct2D and the web service API are not covered) and about half of the book is dedicated to the API code pack which has nothing to do with Windows itself.

  • @Waldek, the Roman numerals system has changed over time. After all it could me a matter of choice what notations and rules are acceptable.

  • @Mark

    It really does seem that way, thankfully this blog has been very active since December and hopefully it will stay that way with STL's help.  He's been a serious beacon of light in this dark time of .net development.

  • @Mark:

    >>> They will probably never make such a list for a simple reason: acknowledging that the majority of their products (the same is true for most of the Fortune 500 companies) is written mostly in native C/C++ would be counterproductive because the marketing guys want to promote .net.

    .NET can be fine for RAD database apps and web sites using ASP.NET, but the vast majority of successful desktop apps (and complex software in general) are written in native C/C++.

    For example, Evernote switched from .NET to C++:

    blog.evernote.com/.../evernote-4-for-windows-is-here

    [QUOTE]

    *Starting from scratch*

    Evernote 4 is a major departure from Evernote 3.5 in every way. While 3.5 added tons of great new features, there were some problems we simply couldn’t fix: the blurry fonts, slow startup times, large memory footprint, and poor support for certain graphics cards were all issues that the technology behind 3.5 (Windows .net and WPF) was incapable of resolving. As a result, we ended up chasing down platform bugs rather than adding the great features our users wanted.

    So we decided to start over from scratch, with fast, native C++ that we knew we could rely on. As you’ll see, the results are amazing. This new version will set a foundation for rapid improvement.

    [/QUOTE]

    I wonder why VS 2010 IDE was rewritten in WPF (I suspect a marketing move...), and I wonder if Microsoft teams like Windows and Office teams really use that WPF IDE.

    Probably a consequence of WPF rewriting of VS2010 IDE can be found here:

    social.msdn.microsoft.com/.../a6d500a2-d4ea-43e2-8460-9283ea5c1d89

  • @ClassicCPPRocks:

    >> .NET can be fine for RAD database apps and web sites using ASP.NET, but the vast majority of successful desktop apps (and complex software in general) are written in native C/C++.

    I agree with you but Microsoft is not marketing .NET that way, they rather say that unless you're doing some low-level system programming you should use .NET.

    >> I wonder why VS 2010 IDE was rewritten in WPF (I suspect a marketing move...), and I wonder if Microsoft teams like Windows and Office teams really use that WPF IDE.

    AFAIK the Windows teams do not use Visual Studio, they have their own build system and use whatever code editor they like.

  • @STL: thanks for the remarks!!

    Regarding the template function: we need you, professor, to deliver a lecture on templates, implicit conversions and so forth now that the STL saga is over. I guess I need that upcoming video more than the others because if you were been my interviewer in this real story, I'd probably not be here telling it -maybe in some other blog, titled "Why I didn't pass" :-P

    @Waldek: you're right, pal. If you check the sample I told right before the epilogue, there are more cases being considered (in fact, the conversion cause enumeration has about 8 entries or so, not just the 3 mentioned here). But the day of the interview, in common agreement with the interviewer, we just stuck to those three as the purpose (like this post) was not to deliver such library function but to show how I reason before a problem. In fact, the whole test was made in the whiteboard so I guess that my solution wouldn't have compiled in the first attempt either :-D

    @rest of you guys, about the debate on "To .NET or Not To .NET", I just want to share some personal thoughts:

    Despite managed code got its industry momentum (especially for enterprise applications) and MS is part of that move since the last decade, I'd like to remind that, unlike other software platform contenders, we’ve never stopped delivering the native C++ development tool.

    I must admit, it's undeniable, that we performed really poorly in terms of C++ promotion like MS Press books, Channel 9 but we are lastly working to increase our participation as much as possible. You haven't mentioned but I honestly will: we haven’t been participating that much in company events like PDC, TechEd, etc. We are also working in improving that and as @Chris pointed out, we increased since December our presence through this blog -let's also mention the creation of the Visual C++ Weekly compiling our weekly tweets- as some initial, concrete measures to be closer to you. I’m amazed to see the degree of participation and response from you.

    The development field is very complex and rich (what, IMHO, makes it so fascinating). Stephan, Ale, Boris, I and the other guys in the Visual C++ team are working to improve our tool and your development experience: that's why your feedback is so important. Other teams at MS and the .NET team in particular will keep doing their best in improving their tooling, so you’ll have choices in terms of Windows development.

    About my personal elections, I feel proud about having worked at production-level with several technologies (from mainframes to Java and .NET, and C and C++ throughout). I love C++ over anything else and I'm ready to defend C++ on the lots of myths being told about it, just with the intention of avoiding C++ being rejected for a project just because of those myths. We'll remain friends if you preferred another language over C++ but you'll probably see me wearing in front of you my favorite T-shirt: "MY COMPILER COMPILED YOURS"

    Keep in touch!!

  • @Diego

    >> I must admit, it's undeniable, that we performed really poorly in terms of C++ promotion like MS Press books, Channel 9 but we are lastly working to increase our participation as much as possible.

    Don't you think it might be interesting to promote C/C++ by showing how it is used today inside Microsoft products like Windows and Office? I think it would help to restore native developers confidence in your commitment.  

    >> [...] so you’ll have choices in terms of Windows development.

    Unfortunately no we do not always have the choice in terms of Windows development. Two recent examples might be Windows Phone 7 and Xbox development: unless you are a Microsoft partner or a major game company you cannot use native code on these platforms, this is not exactly my definition of freedom of choice (and I also think this restriction is a mistake in the long term).

  • [ClassicCPPRocks]

    > Your list is interesting, and I think the majority of the (very successful) projects you mentioned use "classic" C++ (or even pure C, like the kernel), without going crazy with templates or Boost.

    It varies. (Remember that kernel mode is very special.) VC's compiler front-end C1XX is written in relatively modern C++ and uses the STL extensively, while the compiler back-end UTC is written in C and is slowly being converted to C++.

    > C++ rocks, until it gets rocket-science with templates and template metaprogramming.

    Right. Then it rocks harder.

    [Diego]

    > Regarding the template function: we need you, professor, to deliver a lecture on templates, implicit conversions and so forth now that the STL saga is over.

    Heh. It's very likely that I'll cover this in the Advanced STL series (since this appears in the STL's implementation in several places).

    For those who are curious, the answer to the question I posed involves template argument deduction. Given foo(const basic_string<C>&) where C is a template parameter, const char * ptr, and foo(ptr), the compiler must "deduce" what template argument to use for C, since one wasn't provided. This is done by comparing the function parameter type (const basic_string<C>&) to the function argument type. If the function argument were std::string, aka basic_string<char>, the types would match cleanly, and C would be deduced to be char. However, given foo(ptr), the types const basic_string<C>& and const char * don't match cleanly, so the compiler will say that it can't deduce what C is. This is true even though basic_string<char> is constructible from const char *. Template argument deduction doesn't consider implicit conversions (for very good reasons), it just plays a simple game of "make type A match type B".

    For this reason, functions handling both narrow and wide strings are typically overloaded on both const basic_string<C>& and const C *. As a bonus, this increases runtime efficiency.

  • @Diego

    > I must admit, it's undeniable, that we performed really poorly in terms of C++ promotion like MS Press books, Channel 9 but we are lastly working to increase our participation as much as possible. You haven't mentioned but I honestly will: we haven’t been participating that much in company events like PDC, TechEd, etc. We are also working in improving that ...

    I am going to be harsh.

    Don't waste your time on this. Please stop thinking that what you are suffering from is too little promotion. You are suffering from the bad quality of the product that is VC2010.

    Instead of spending time on "increasing visibility" of C++ and unmanaged code, fix the numerous issues with the product raised by customers. I previously posted on this blog mentioning that the debugger frequently refuses to show values of variables. Let me remind you that the debugger is frequently the only thing that keeps people in your slow and degrading IDE, and prevents them from moving to other products. Let me remind you that being able to browse values of variables is one of the most important features of the debugger, a game-breaking one. Let me assure you that the issue where the debugger fails to display values of variables occurs more and more frequently the larger your codebase gets, at some point you start running into this issue several times a day in different places in code. The Connect database has seen this issue reported a number of times. Let's take a look at how you deal with these issues...

    Exhibit 1:

    connect.microsoft.com/.../vc-express-debugger-doesnt-see-some-variables

    A very clear repro, several inquisitive users who dig deep into what's going on and are bending over their backs to help get the issue fixed. Your developer takes a single look at the problem almost 2 months after it is submitted, quickly decides that it must be related to optimization without doing any investigation, and closes the issue. ..."Your variable is not used after initialization, so it must be optimization, I am closing the issue, mwahaha" - that's what he (read: you) did. After the brush off, one of the commenters posts a modified version of the repro, which does use variables after initialization and exhibits the same problem - but, of course, it's too late.

    Exhibit 2:

    connect.microsoft.com/.../cannot-inspect-local-variables-while-debuggin-in-vs2008-and-vs2010-cxx0017-symbol-not-found-error

    Same issue with the debugger not being able to show the values of variables. Another very clear repro. What you are doing here? Easy - nothing. For 6 months since the issue has been reported - nothing. No replies, no investigation, nothing. You are too busy making your editor slower and making your help system less usable.

    There are at least 5 more issues on Connect that are dedicated to what looks to be the same problem with the debugger and that go like exhibits above or worse. In one case you leave the issue unattended for a long time and when you actually get to it, all you have to say that you can repro the issue, but you are going to close it because the issue doesn't pass some imaginary "bug bar". Seriously??! Who cares about your bars? The issue is real, it affects your customers, it is important, yet you are going to close it and forget about it because it doesn't meet some bizarre criteria for bugs you use prior to getting your releases out the door?! Ridiculous.

    There are a couple of issues on Connect dedicated to what looks to be the same problem where you appear to be actually doing something. For example, in one case you say that you fixed the reported problem in your code. However, you also say that we won't get the fix until the next major version of VS and so there's no way to tell whether your fix actually fixes the problem even in all of the reported repros, yet alone in all manifestations of the problem in real life. Given your past performance, there is a good chance that your fix actually fixes very little - you were reporting that you fixed the issue prior to VS2008 as well. But cases where you even appear to be doing something are far and few between cases where you just talk, eg, about maybe fixing the problem later, or where you do nothing or where you do everything you can to close the issue on Connect without showing interest in fixing the underlying problem, like in exhibits shown above.

    That's why people say that reporting bugs to you is pointless. And that's why VC2010 is such a terrible product.

  • @Mark: for sure, showcasing how we apply C++ indoor in our two flagship prods is an awesome initiative and I'm working these days, among other plans, with the Channel9 guys to start a series on C++ at MS.

    Regarding your thoughts about C++ only available for partners in non-Windows, yet MS-owned platforms like XBox and WinPhone, I'm confident that some decisions will be reviewed. I'm not making any announcement in saying this, just want to say that I'm advocating for yours and other folks here wishes regarding C++ development availability in every platform other than the PC one. I'm definitively use your own comment hear to reaffirm that need.

    @STL: thanks!

    @PleaseFixYourBugs: thanks for speaking up. I took a look to those connect bugs you pasted (thanks about that) and also some few related connect bugs that the ones you pasted are mentioning. I tried to reproduce all those examples as explained (setting the breakpoint properly, stepping over if required, etc.) in VS2010 SP1 Beta (released last month). Using that environment (must also mention Win 7 Enterprise x64) I couldn't reproduce those examples. I'm still owing to do this same with VC++ Express (as one of the connect bugs mentioned that platform, the other was talking about VS10 Ultimate in Win 7 Pro x64).

    What I did was creating a separated project for each case (solutions, projects and sources) plus a screenshot where I'm just suggesting -I need you to reconfirm- that with the SP1 Beta at least the issue seems to be solved.

    Don't get me wrong: I'm not saying "norepro" here, and I'm escalating the problem using your own post. I'd like you to reconfirm that you are still experiencing the issue and the exact environment you are using (OS version, VS version, etc.)

    I'll also try tonight this same using VC++ 2010 Express.

    The projects I included in this zip are the following:

    -DebugVars1: based on Damir Valiulin in connect.microsoft.com/.../cannot-inspect-local-variables-while-debuggin-in-vs2008-and-vs2010-cxx0017-symbol-not-found-error

    -DebugVars2: based on PowerGamer1 in both connect bugs you pasted.

    -DebugVars3: the most arguable of the three as karwosts talked about VC++ Express and I haven't tried it with that tool (but I will tonight). My test with VS2010 SP1 Beta worked fine suggesting that it could have been solved but was not communicated in the original connect bug connect.microsoft.com/.../vc-express-debugger-doesnt-see-some-variables

  • @Diego: Where one could get the "MY COMPILER COMPILED YOURS" T-shirt? I simply MUST have it! :D

Page 1 of 3 (35 items) 123