4

例を考えてみましょう:

#include <iostream>
#include <vector>

template <class, class T>
using alias = T;

template <template <class...> class>
struct tt_wrapper{};

template <class...>
struct t_wrapper{};

struct A {
    template <template <class...> class TT, class T>
    void foo(alias<tt_wrapper<TT>, T>) { std::cout << "A::foo invoked" << std::endl; }
};

struct B: A {
    using A::foo;
    template <class U, class T>
    void foo(alias<t_wrapper<U>, T>) { std::cout << "B::foo invoked" << std::endl; }
};

int main() {
    B b;
    b.foo<std::vector>(int{});
}

[namespace.udecl]/15によると:

using-declaration が名前を基本クラスから派生クラス スコープに持ち込む場合、派生クラスのメンバー関数とメンバー関数テンプレートは、同じ名前、parameter-type-list、cv を持つメンバー関数とメンバー関数テンプレートをオーバーライドおよび/または非表示にします。 -qualification、および ref-qualifier (存在する場合) を基本クラスに (競合するのではなく)

したがって、明らかにテンプレート パラメーターは、メンバー関数の非表示に関与するべきではありません。ただし、この例では、テンプレート パラメーターはエイリアスを使用して署名に取り込まれます。それにもかかわらず、 clangは、エイリアスが関数のparameter-type-list の一部であり、次のように主張しているという感覚を共有していないようです。

prog.cc:26:7: error: no matching member function for call to 'foo'
    b.foo<std::vector>(int{});
    ~~^~~~~~~~~~~~~~~~
prog.cc:21:10: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'U'
    void foo(alias<t_wrapper<U>, T>) { std::cout << "B::foo invoked" << std::endl; }
         ^
1 error generated.

非表示プロセスにテンプレート パラメーター リストが含まれるため、意図的に gcc を省略しました。クランは正しいですか?

4

1 に答える 1