私は比較的一般的なものを探しています:
- このコード行をコンパイルしてみてください
- それが成功した場合は、そのコード行をコンパイルして使用します。さもないと
- 他のコード行を使用する
double
提供されたファンクターがsで有効かどうかに基づいて、何かを選択的にコンパイルしたい場合があります。
//Some user supplied functor I can't modify which works on `int` but not `double`
template<typename T>
struct LShift : std::binary_function<T, T, T>
{
T operator()(T lhs, T rhs)
{
return lhs << rhs;
}
};
//Class that holds either an int or a double
class Example
{
union
{
int intVal;
double dblVal;
} value;
bool isIntType;
public:
Example(int val)
: isIntType(true)
{
value.intVal = val;
}
Example(double val)
: isIntType(false)
{
value.dblVal = val;
}
int GetIntergalValue() const
{
return value.intVal;
}
double GetDoubleValue() const
{
return value.dblVal;
}
bool IsIntegral() const
{
return isIntType;
}
};
//Does something with an example. I know that if the examples have `double` contents,
//that the functor passed will also be valid for double arguments.
template <template <typename Ty> class FunctorT>
Example DoSomething(const Example& lhs, const Example& rhs)
{
if (lhs.IsIntergal() != rhs.IsIntergal())
{
throw std::logic_error("...");
}
if (lhs.IsIntegral())
{
return Example(FunctorT<int>(lhs.GetIntergalValue(), rhs.GetIntergalValue()));
}
else
{
return Example(FunctorT<double>(lhs.GetDoubleValue(), rhs.GetDoubleValue()));
}
}
int main()
{
DoSomething<LShift>();
}
これまで SFINAE を使用したことはありませんが、これが最初の試みでした。
template <template <typename Ty> class FunctorT>
double DoDouble(double lhs, double rhs)
{
return FunctorT<double>()(lhs, rhs);
}
template <template <typename Ty> class FunctorT>
double DoDouble(int lhs, int rhs)
{
throw std::logic_error("That is not valid on floating types.");
}
最初のオーバーロード (double を渡した場合により良いオーバーロードであるため選択される) で置換が失敗し、その制御が 2 番目のオーバーロードに進むと考えました。ただし、とにかく全体がコンパイルに失敗します。
私がやろうとしていることは合理的または可能ですか?