7

以下では、GCC はテンプレート構造体をclass のnameテンプレート メンバー関数と混同しますが、Clang は正常にコンパイルされます ( live example )。nameA

template<typename T>
struct name {};

struct A
{
    template<bool B>
    void name() { }
};

template<bool B, typename T>
void f(T& x) { x.template name<B>(); }

この例では、関数fは明らかに type の引数で呼び出されることを意図していますが、それ以外のものである可能性があるため、テンプレート関数のままにする必要があります。Af

どのコンパイラが正しいかはあまり気にしません。回避策が必要なだけです。

x.template name<B>();

usingメンバー関数を呼び出すには、宣言やその他の明確化の方法がどのように適用されるかわかりません。

編集はい、より明示的な構文を試しました

x.T::template name<B>();

これは機能しますが、本当に醜いです。簡単な構文を機能させる方法はありますか? それ以外の場合は、最初に 2 つの名前のいずれかを変更することをお勧めします...

EDIT2私の元のバージョンは、最も醜いものを必要とfするユニバーサルリファレンスで動作しますT&&

using X = typename std::remove_reference<T>::type;
x.X::template name<B>();

場合Tは参照です...そして、これはすべて単純な関数呼び出しです。

4

3 に答える 3

1

私はこれについて少し考えましたが、すべてのテンプレートが関係しているため、必要な最も基本的な構文を機能させる方法がわかりません。指定する必要がある理由は、そうしないと、関数のアドレスを と比較するためにtemplate使用しているようにコンパイラに見えるためです。<B

あなたが言ったnameように、識別子の1つの名前を変更するだけで、コンパイラがどれを意味するかについてあいまいさをなくすことができます。

または、あなたが言ったことを正確に行い、通話を完全に修飾することもできます。私はこれが醜い構文だとは思いません:何が起こっているのか正確に読者に完全に明らかです。

template<bool B, typename T>
void f(T& x)
{
    typedef typename std::remove_reference<T>::type callee;

    x.callee::template name<B>();
}

最後に、このテンプレートで解決しようとしている実際の問題についてもう少し詳しく説明していただければ、そのような型のエイリアシングをまったく含まない直交ソリューションを提供できるかもしれません。

于 2014-06-20T18:47:36.283 に答える
0

名前空間も使用できます。

「構造体名」を名前空間に入れて、構造体名を NS::name として参照します。

namespace NS
{
    template<typename T>
    struct name {};
}

このようなメソッドで元の x.template name() を使用できます。

于 2014-07-28T02:02:35.803 に答える