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

发布于 2024-11-16 16:30:51 字数 2144 浏览 4 评论 0原文

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

  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.");
}

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

我想做的事情合理或可能吗?

I'm looking for a relatively generic:

  1. try to compile this line of code
  2. if that succeeds, compile and use that line of code. Otherwise
  3. use some other line of code

I've got a case where I'd like to selectively compile something based on whether the supplied functor is valid on doubles:

//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>();
}

I've never used SFINAE before, but this was my first attempt:

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.");
}

I thought substitution would fail on the first overload (which would be selected because it's a better overload when passed doubles), and that control would then proceed to the second overload. However, the whole thing fails to compile anyway.

Is what I'm trying to do reasonable or possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

沉睡月亮 2024-11-23 16:30:51

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

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。

但有一股浓烈的气味。未调用专业化的代码(!)很可能应该被重构。在某种程度上。

干杯&呵呵,

Try this (it's off the cuff, may have syntax erors):

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;
}

Alternatively you can use SFINAE via Boost enable_if.

But there is a strong smell about it. The code where the specialization is not invoked (!) should most probably be refactored. In some way.

Cheers & hth.,

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文