c++ - 如果原始源代码行无法编译,是否可以让模板选择备用源代码行?

标签 c++ templates sfinae

我正在寻找一个相对通用的:

  1. 尝试编译这行代码
  2. 如果成功,编译并使用该行代码。否则
  3. 使用其他代码行

我有一个案例,我想根据提供的仿函数在 double 上是否有效来有选择地编译一些东西:

//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 时它是更好的重载),然后该控制将继续进行第二次重载。然而,整个事情无论如何都无法编译。

我正在尝试做的事情是否合理或可行?

最佳答案

试试这个(即兴的,可能有语法错误):

template < class Type >
Type ShiftLeft( Type lhs, Type rhs )
{
    return LShift( lhs, rhs );
}

template <>
double ShiftLeft( double lhs, double rhs )
{
    assert( "ShiftLeft is not valid on floating types." && false );
    return 0;
}

或者,您可以通过 Boost enable_if 使用 SFINAE。

但它有一股浓烈的气味。未调用特化 (!) 的代码最有可能被重构。在某种程度上。

干杯,

关于c++ - 如果原始源代码行无法编译,是否可以让模板选择备用源代码行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6460730/

相关文章:

php - Twig 模板的分析器

c++ - 我的 SFINAE 检查 std::map/std::vector 有什么问题?

c++ - 如何检测 std::integer_sequence 中特定数字的索引?

c++ - 通过具有模板专长的基类以const方法调整本地容器的大小

c++ - 获取与字符串对应的类型,如 int、float 等

c++ - 以下会不会引起内存问题?

c++ - 如何保持 boost asio async 连续读取事件

c++ - 如何在 C++ 中动态存储和访问类型?

c++ - 静态断言类型 A 可以从类型 B 构造

c# - 如何使用 C++/CLI Wrapper 将变量参数从托管传递到非托管?