• C++11: Template argument deduction, partial ordering, and trailing para

    From Christoph Schulz@21:1/5 to All on Sat Feb 20 15:19:09 2016
    Hello,

    I read §14.8.2.1, §14.8.2.4, and §14.8.2.5 multiple times but did not find
    a convincing argumentation why the second of the following two function templates is more specialized for the given argument than the first one:

    ========= %< =========
    #include <ostream>
    #include <iostream>

    template<int ...T>
    struct X {};

    // #1
    template<int I, int ...Ints>
    int f(X<I, Ints...> x) {
    return I + f(X<Ints...>{});
    }

    // #2
    template<int I>
    int f(X<I>) {
    return I;
    }

    int main()
    {
    std::cout << f(X<1>{}) << std::endl; // selects #2
    }
    ========= %< =========

    The compiler I used (g++ 4.9.3) has no problems compiling this code. But
    I don't understand why. For both #1 and #2, "I" can be deduced to be "1",
    and in #1, "Ints..." can be deduced to be an empty list of int values,
    making the parameter type be "X<1>" in both cases. (This can be "proven"
    by removing #1 or #2 from the overload set by #if 0 ... #endif, and seeing
    the code compile successfully in both cases.) So, according to
    §13.3.3/1, partial ordering of function templates should disambiguate this case. But which rule makes #2 more specialized than #1? In this situation, §14.8.2.5/9 seems to apply, but the sentence

    - if P does not contain a template argument corresponding to Ai then Ai
    is ignored;

    seems to support the interpretation that #1 can be deduced from #2.

    Can anybody shed some light on it? I'm sure that I overlooked
    something... Or does g++ behave simply wrong?


    Best regards,

    --
    Christoph Schulz


    [ comp.std.c++ is moderated. To submit articles, try posting with your ]
    [ newsreader. If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
    [ --- Please see the FAQ before posting. --- ]
    [ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Christof Meerwald@21:1/5 to Christoph Schulz on Wed Mar 16 01:07:30 2016
    On Sat, 20 Feb 2016 15:19:09 CST, Christoph Schulz wrote:
    ========= %< =========
    #include <ostream>
    #include <iostream>

    template<int ...T>
    struct X {};

    // #1
    template<int I, int ...Ints>
    int f(X<I, Ints...> x) {
    return I + f(X<Ints...>{});
    }

    // #2
    template<int I>
    int f(X<I>) {
    return I;
    }

    int main()
    {
    std::cout << f(X<1>{}) << std::endl; // selects #2
    }
    ========= %< =========

    Isn't that kind of what core issues 1395
    http://wg21.cmeerw.net/cwg/issue1395 and 1432 http://wg21.cmeerw.net/cwg/issue1432 are about?

    g++ is likely implementing the proposed resolution, but that
    resolution hasn't been incorporated into the standard text yet.


    Christof


    --
    http://cmeerw.org sip:cmeerw at cmeerw.org mailto:cmeerw at cmeerw.org xmpp:cmeerw at cmeerw.org


    [ comp.std.c++ is moderated. To submit articles, try posting with your ]
    [ newsreader. If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
    [ --- Please see the FAQ before posting. --- ]
    [ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Christoph Schulz@21:1/5 to Christoph Schulz on Wed Mar 16 01:07:54 2016
    Hello!

    Christoph Schulz wrote:

    Hello,

    I read §14.8.2.1, §14.8.2.4, and §14.8.2.5 multiple times but did not find a convincing argumentation why the second of the following two function templates is more specialized for the given argument than the first one: [...]

    I just learned that clang++ (version 3.7.0) barks at the code:

    main.cpp:21:18: error: call to 'f' is ambiguous
    std::cout << f(X<1>{}) << std::endl; // selects #2
    ^
    main.cpp:9:5: note: candidate function [with I = 1, Ints = <>]
    int f(X<I, Ints...> x) {
    ^
    main.cpp:15:5: note: candidate function [with I = 1]
    int f(X<I>) {
    ^
    1 error generated.

    Perhaps my assumption that this code is ambiguous is indeed correct. Nevertheless I would like to see it confirmed by some other C++ expert(s)
    ;-)


    Best regards,

    --
    Christoph Schulz


    [ comp.std.c++ is moderated. To submit articles, try posting with your ]
    [ newsreader. If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
    [ --- Please see the FAQ before posting. --- ]
    [ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)