編集:私の質問に対する簡単な答えは、SFINAE ができることについて間違った見方をしており、関数本体をまったくチェックしていないということです: sfinae は関数本体をインスタンス化しますか?
これに似た問題があります:関数の存在を確認するテンプレートを作成することは可能ですか?
違いは、関数が存在するかどうかを確認するだけでなく、実際に SFINAE を渡すかどうかも知りたいということです。これが私が達成しようとしているものの例です:
struct A
{
void FuncA() { std::cout << "A::FuncA" << std::endl; }
};
struct B
{
void FuncA() { std::cout << "B::FuncA" << std::endl; }
void FuncB() { std::cout << "B::FuncB" << std::endl; }
};
template<typename T>
struct Inter
{
void FuncA() { t.FuncA(); }
void FuncB() { t.FuncB(); }
T t;
};
// Always takes some sort of Inter<T>.
template<typename InterType>
struct Final
{
void CallFuncs()
{
// if( t.FuncA() exists and can be called )
t.FuncA();
// if( t.FuncB() exists and can be called )
t.FuncB();
}
InterType t;
};
void DoEverything()
{
Final<Inter<A>> finalA;
Final<Inter<B>> finalB;
finalA.CallFuncs();
finalB.CallFuncs();
}
CallFuncs() では、FuncA() と FuncB() の両方が常に存在しますが、Inter で使用される型 T によってはコンパイルされない場合があることに注意してください。上記のリンクされた質問の回答を使用しようとすると、実際にコンパイルできることではなく、関数が存在することを確認するだけであるため、常に真になるように思われます(ただし、それを除外することはできません)何かを台無しにしたわけではありません...)
関数を条件付きで呼び出すために、 enable_if をそのまま使用できると思います。
template<typename InterType>
typename std::enable_if< ! /* how to determine if FuncA can be called? */>::type TryCallFuncA( InterType& i )
{
}
template<typename InterType>
typename std::enable_if</* how to determine if FuncA can be called? */>::type TryCallFuncA( InterType& i )
{
i.FuncA();
}
template<typename InterType>
typename std::enable_if< ! /* how to determine if FuncB can be called? */>::type TryCallFuncB( InterType& i )
{
}
template<typename InterType>
typename std::enable_if</* how to determine if FuncB can be called? */>::type TryCallFuncB( InterType& i )
{
i.FuncB();
}
template<typename InterType>
struct Final
{
void CallFuncs()
{
TryCallFuncA(t);
TryCallFuncB(t);
}
InterType t;
};
しかし、ブール値をenable_ifに渡す方法があるかどうかはわかりません。これを達成する方法はありますか、または関数が存在するかどうかを示す何らかの手動で維持される型特性にフォールバックする必要がありますか?
利用可能な C++11 機能セットに関する限り、私は MSVC 2010 を使用しています。
編集: 重要なメモを追加するには、私の実際の状況では、クラス Inter の実装は、Inter::FuncA/FuncB がコンパイルされるかどうかを判断する必要がある時点で事実上不透明であるため、子をバブルアップすることはできません型を調べ、関数が存在するかどうかを確認します。