Template parameters not displayed in partial specialization in gcc6 for the case that was used to work in gcc5

This code leads to an error in gcc6 (but works fine in gcc 4.8, 5.2 and clang 3.6):

template <typename T>
struct outer
{
    template <typename U>
    struct inner
    {

    };
};


template <typename T>
struct is_inner_for
{

    template <typename Whatever>
    struct predicate
    {
        static constexpr bool value = false;
    };

    template <typename U>
    struct predicate<typename outer<T>::template inner<U>>
    {
        static constexpr bool value = true;
    };
};

static_assert(
    is_inner_for<int>::template predicate<
        outer<int>::inner<double>
    >::value,
    "Yay!"
);

Error:

main.cpp:22:9: error: template parameters not deducible in partial specialization:
  struct predicate<typename outer<T>::template inner<U>> : std::true_type
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:22:9: note:         'U'
 ^~~~~~~~~~~~~

Command line:

g++ -std=c++1y -c main.cpp

See godbolt's release here .

I filed an error with gcc here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70141

However, this was noted as invalid (I consider erroneous). outer<T>, which is used internally predicate, is a specific type at this point, so it is not an irreducible context.

Is there anything in the standard that prevents this from being valid C ++ code?

+4
1

, gcc 6.0 clang 3.9 ( - , , , ).


[temp.class.spec.match]:

,

U typename outer<T>::template inner<U> outer<int>::inner<double>?

[temp.deduct.type]:

, .

:
- - , .
- [...]

typename outer<T>, , . . , .

:

#include <utility>

template <class >
struct outer
{
    template <class U> struct inner {};
};

template <class T>
struct bar {
    template <class U> std::false_type foo(U const&);
    template <class U> std::true_type foo(typename outer<T>::template inner<U> const&);
};


int main() {
    static_assert(decltype(bar<int>{}.foo(outer<int>::inner<double>{}))::value, "!");
}

gcc 6.0 clang 3.9 - , .

+3

All Articles