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

时间:2011-06-23 21:18:53

标签: c++ templates sfinae

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

  1. 尝试编译这行代码
  2. 如果成功,则编译并使用该行代码。否则
  3. 使用其他一些代码
  4. 我有一个案例,我想根据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.");
    }
    

    我认为替换会在第一次重载时失败(这会被选中,因为当传递双精度时它是一个更好的重载),然后该控制将进入第二次重载。然而,无论如何整个事情都无法编译。

    我想做的是合理的还是可能的?

1 个答案:

答案 0 :(得分:2)

试试这个(它不在袖口,可能有语法错误):

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。

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

干杯&amp;第h。,