1

SFINAE の原則は、Visual Studio 2010 で非常に単純に見えるものに対しては機能しません。

#include <type_traits>
#include <iostream>

struct MyStruct
{
  int value;
  MyStruct(int value = 42) : value(value) { }
  const int& getInt() const { return value; }
};

template <typename ITER_TYPE>
auto getIteratorInt(ITER_TYPE iter) ->
  typename std::enable_if
  <std::is_pointer<decltype(*iter)>::value, const int&>::type
{
  return (*iter)->getInt();
}

template <typename ITER_TYPE>
auto getIteratorInt(ITER_TYPE iter) ->
  typename std::enable_if
  <!std::is_pointer<decltype(*iter)>::value, const int&>::type
{
  return iter->getInt();
}

int main(void)
{
  MyStruct gloryInt;
  MyStruct* gloryIntPtr = &gloryInt;
  std::cout << getIteratorInt(gloryIntPtr) << std::endl;
  std::cout << getIteratorInt(&gloryIntPtr) << std::endl;
  return 0;
}

私の意図はstd::enable_if、SFINAE 原則に基づいて正しいテンプレート オーバーロードをコンパイルするために使用することです。(既存の戻り値の型を持たない関数は無視され、もう一方はコンパイルされます。) そうすれば、オブジェクトへのポインターまたはダブル ポインターを使用でき、直接のオブジェクトは引き続きアクセスされます。

次のコンパイル エラーが発生します。

main.cpp(14): error C2039: 'type' : is not a member of 'std::tr1::enable_if<_Test,_Type>'
          with
          [
              _Test=false,
              _Type=const int &
          ]
main.cpp(17): error C3646: 'type' : unknown override specifier

SFINAE が使用されていない場合、これは非常に明白なエラーです。Visual Studio 2010 で目的の機能を取得する方法はありますか?

4

1 に答える 1

2

他の回答を更新する前に、プロフィール ページを確認する必要がありました。

decltype( * iter )は をint const *const &参照します。これは、「生の」ポインタではなく、ポインタへの参照です。したがってstd::is_pointer、予期しない結果が返されます。これを解決するには、次の 2 つの方法があります。

  • std::iterator_traits私が好む C++03 から使用します。

    typename std::iterator_traits< ITER_TYPE >::value_type
    
  • std::decay参照を取り除くメタ関数を使用してdecltype、式の値カテゴリを反映するために追加する可能性があります

    typename std::decay< decltype( * iter ) >::type
    
于 2012-04-10T09:44:41.650 に答える