1

次のかなり単純なクラスを想定します。

struct A {
    bool toBool() const { return true; }
    template<typename T> T to() const { return T();}
};

ここで、次の存在をテストしたいと思いますtoBool

template<typename From, typename To>
class has_toBool_func
{
    typedef char (&Two)[2];
    template<typename F, bool (F::*)() const> struct helper {};
    template<typename F> static char test(helper<F, &F::toBool>*);
    template<typename F> static Two test(...);
public:
    static const bool value = (sizeof(test<From>(0)) == sizeof(char));
};

が定義され、使用されます。

::std::cout << "int: " << has_toBool_func<int, bool>::value
    << ", A: " << has_toBool_func<A, bool>::value << ::std::endl;

そして、期待される出力 "int: 0, A: 1" だけが生成されます。

関数テンプレートに対して同じことを試してみてください:

class has_to_func
{
    typedef char (&Two)[2];
    template<typename F, To (F::*)() const> struct helper {};
    template<typename F> static char test(helper<F, &F::to<To> >*);
    template<typename F> static Two test(...);
public:
    static const bool value = (sizeof(test<From>(0)) == sizeof(char));
};

::std::cout << "int: " << has_to_func<int, bool>::value
    << ", A: " << has_to_func<A, bool>::value << ::std::endl;

期待される出力 "int: 0, A: 1" ではなく、コンパイル エラーが発生します。

なぜこうなった?そしてもちろん:どうすれば修正できますか?

MSVC 2012

警告を与える

warning C4346: 'F::to' : dependent name is not a type  
      prefix with 'typename' to indicate a type  
      see reference to class template instantiation 'xtd::has_to_func<From,To>' being compiled

従属名は実際にはタイプではなくエラーであるため、これは役に立ちません

error C2998: 'char test' : cannot be a template definition

これもあまり役に立ちません...

ICC13.0

最初にエラーを与える

error : type name is not allowed  
        template<typename F> static char test(helper<F, &F::to<To>() >*);  

(<To>はマークされています)

これは問題を説明していますが、なぜこれが発生したのか、別のエラーが発生したのかについては完全にわかりません

error : expected a ")"  
        template<typename F> static char test(helper<F, &F::to<To>() >*);  

(最後>に印がついています)

これは完全なぼろぼろであり、コンパイラが混乱したためにのみ表示されていると確信しています。

4

1 に答える 1

4

&F::to<To>にテンプレート引数として渡すときは括弧を使用しないでください。曖昧さ回避ツールを使用して、次のことをコンパイラに伝えるhelper必要があります。template

  • toテンプレートの名前として解釈する必要があります。
  • 後続の角括弧は、より小なり大なりとして解釈されるのではなく、テンプレート引数を区切る必要があります。

template<typename F> static char test(helper<F, &F::template to<To> >*);
//                                              ^^^^^^^^^^^^^^^^^^^

Tの戻り型として追加した後A::to<>()、これはうまくいくようです(GCC 4.7.2でテスト済み)。これが実際のです。

于 2013-05-07T08:35:00.163 に答える