9

私が持っている一部のコードがコンパイルされない理由を理解しようとしており、匿名化をかなり削減して、この例になります。

#define NULL ((void*)0)
template<typename T>
class a {
public:
  template<bool b>
  T * amem() {
    return NULL;
  }
};

template<typename T>
class b {
public:
  a<T>* ap;

  template <bool b>
  T * m() {
    return ap->amem<b>();
  }
};

int main()
{
  return 0;
}

使用するコンパイラと変数の名前に応じて、さまざまなエラーが発生します。ただし、それらはすべてこの行を中心にしています。

    return ap->amem<b>();

clang++ [Apple clang バージョン 4.0 (tags/Apple/clang-421.0.57) (LLVM 3.1svn ベース)] を使用してコンパイルすると、次のメッセージが表示されます。

tmp.cpp:18:26: error: expected expression
      return ap->amem<b>();
                         ^
1 error generated.

g++ [i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1] を使用してコンパイルすると、次のメッセージが表示されます。

tmp.cpp: In member function ‘T* b<T>::m()’:
tmp.cpp:18: error: expected primary-expression before ‘&gt;’ token
tmp.cpp:18: error: expected primary-expression before ‘)’ token

不思議なことに(とにかく、私には)。amem の名前を m に変更すると、g++ からはエラーが発生しなくなりますが、clang++ からは同じエラーが発生します。

ここに私が理解できない何かがあると確信していますか?clang と gcc が探している式を知っている人はいますか? この問題を解決する方法を知っている人はいますか?

これがコンパイラのバグである場合 (疑わしいと思われます)、amem を (テンプレートではなく) bool パラメーターを持つ関数に変換することを伴わない回避策を知っている人はいますか? 私はすでにこれを行っており、これが問題を回避することを確認できますが、これはホット ループ内にあり、b によってオンに切り替えられたコードは、おそらくホット ループにあってはならないメモリ割り当てです。

4

2 に答える 2

26

templateキーワードを追加する必要があります:

return ap->template amem<b>();

「template」および「typename」キーワードをどこに、なぜ入力する必要があるのか​​をお読みください。詳細な説明のために。

于 2012-11-11T23:43:46.453 に答える
3

あなたが呼ぶ文脈で

return ap->amem<b>();

名前amemは従属名です:そのような獣が実際にメンバー関数テンプレートを参照している場合は、キーワードを追加してそのように言う必要がありますtemplate

return ap->template amem<b>();

ところで、あなたは定義してはならないことに注意してくださいNULL!忌まわしきの定義が必要な場合は、たとえば、を含める必要がありますcstddef0そのまま使用するかnullptr、C++2011を使用する場合に最適です。

于 2012-11-11T23:48:21.480 に答える