locked
VS2013 templates: Why doesn't this code cause a compiler error message? RRS feed

  • Question

  • Hi everyone,

    I am exploring the C++11 templates in VS2013. Consider the following declarations:

    template<typename __LEFT, typename... __REST>
    auto Max(__LEFT const &left, __REST... rest) -> decltype(true ? Max(rest...) : left)
    {
        auto right = Max(rest...);
        return right > left ? right : left;
    }
    
    template<typename __LEFT>
    auto Max(__LEFT const &arg1) -> __LEFT
    {
        return arg1;
    }
    

    I imagine this gives me a function 'Max' which takes any number of arguments and returns the highest value of all, given the arguments can be greater-than compared. Now comes the test code:

    int i; i = Max(1); i = Max(4, 2); i = Max(1, 2, 3); double d; d = Max(1.1, 2); d = Max(0, -4.5, 10); CString str1, str2, str3; CString str4 = Max(str1, str2, str3); auto x = Max(str1, 4.1); x = 7; TRACE(_T("%d"), x);

    The first few tests run as expected, even the test with CString works (not a very good test because all strings are empty...), but I would expect to see a compiler error in the line 'auto x = Max(str1, 4.1);' because no greater-than comparison between CString and double is defined, so the compiler cannot instantiate the Max template for this call. What happens, instead, is that the compiler issues "warning C4700: uninitialized local variable 'x' used" in the 'TRACE' line. When I look at the generated machine code, I see that no code (0 bytes) is generated for the 'auto' and the 'x=7' lines.

    Can anyone tell me why?

    (I also tried 'std::comon_type_t<Max(rest...), left>' instead of 'decltype(true ? Max(rest...) : left)' but with identical result.)

    Thanks

    Hans

    Sunday, April 12, 2015 6:41 PM

Answers

  • That's some sort of compiler bug. VS2015 produces a bunch of errors:

    main.cpp(30): error C2780: '__LEFT Max(const __LEFT &)': expects 1 arguments - 2 provided
    main.cpp(11): note: see declaration of 'Max'
    main.cpp(30): error C2893: Failed to specialize function template 'unknown-type Max(const __LEFT &,__REST...)'
    main.cpp(30): note: With the following template arguments:
    main.cpp(30): note: '__LEFT=ATL::CString'
    main.cpp(30): note: '__REST={double}'
    main.cpp(31): error C3536: 'x': cannot be used before it is initialized

    • Marked as answer by H4N51 Tuesday, April 14, 2015 5:11 PM
    Monday, April 13, 2015 5:23 AM

All replies

  • That's some sort of compiler bug. VS2015 produces a bunch of errors:

    main.cpp(30): error C2780: '__LEFT Max(const __LEFT &)': expects 1 arguments - 2 provided
    main.cpp(11): note: see declaration of 'Max'
    main.cpp(30): error C2893: Failed to specialize function template 'unknown-type Max(const __LEFT &,__REST...)'
    main.cpp(30): note: With the following template arguments:
    main.cpp(30): note: '__LEFT=ATL::CString'
    main.cpp(30): note: '__REST={double}'
    main.cpp(31): error C3536: 'x': cannot be used before it is initialized

    • Marked as answer by H4N51 Tuesday, April 14, 2015 5:11 PM
    Monday, April 13, 2015 5:23 AM
  • Assuming this is in an int main() function, If you add return x; then the compiler will crash with an ICE.

    (PSA: The use of a double underscore is reserved.  Try to break that bad habit.)

    Monday, April 13, 2015 5:17 PM
  • I had suspected it is a compiler bug, but wasn't sure whether it was only my not-so-good understanding of C++11 templates. I will eventually have to change to VS2015 :-)

    • Edited by H4N51 Tuesday, April 14, 2015 5:13 PM
    Tuesday, April 14, 2015 5:12 PM
  • >> The use of a double underscore is reserved.

    Good point. According to the referenced page, even single underscores are reserved. Is there a convention on naming template and macro parameters?

    Tuesday, April 14, 2015 5:15 PM
  • >> The use of a double underscore is reserved.

    Good point. According to the referenced page, even single underscores are reserved. Is there a convention on naming template and macro parameters?

    Nothing you can't adjust for your own taste. But don't get too hung up on naming them differently.  Ideally name them like function parameters.  Having said that, the most prolific stylization goes like this:

    For single parameters:

    template<typename T>

    ...literally, just always letter 'T' unless they are nested in which case T becomes U, and U becomes V, etc.

    And then for multiple parameters you can prefix them with a T.

    template <typename TFoo, typename TBar, typename TBaz>

    And if they are non-type parameters, then they often tend to be capitalized.

    template <int N, size_t COUNT>

    But naming them like function parameters is also perfectly fine (and less likely to collide with a preprocessor MACRO I find.)

    template <typename T, int level, int index>



    • Edited by Wyck Tuesday, April 14, 2015 7:48 PM minor spelling mistake.
    Tuesday, April 14, 2015 7:47 PM
  • Thanks for the advice. I'll keep it in mind as I continue to write code, and will eventually develop my own style of naming emplate and macro parameters :-)
    Wednesday, April 15, 2015 4:57 PM