【问题标题】:How to omit copying function definition for different parameters in C++如何在 C++ 中省略不同参数的复制函数定义
【发布时间】:2016-06-10 12:27:48
【问题描述】:

我有很多代码以某种方式执行完全相同的操作(继承的代码),我希望在重新处理它的同时压缩代码而不丢失功能。例如让我们看看以下函数:

fnc(largetype & a,  largetype & b)  { f(A); f(B); };
fnc(largetype && a, largetype & b)  { f(A); f(B); };
fnc(largetype & a,  largetype && b) { f(A); f(B); };
fnc(largetype && a, largetype && b) { f(A); f(B); };

它们都在做完全相同的事情,但参数可以是右值或左值,而不会破坏函数逻辑。我想允许用户传递任何适合问题的东西,但我也不想一块一块地复制粘贴所有代码。我可以这样做:

fnc(largetype & a,  largetype & b)  { f(A); f(B); };
fnc(largetype && a, largetype & b)  { fnc(a,b) };
fnc(largetype & a,  largetype && b) { fnc(a,b) };
fnc(largetype && a, largetype && b) { fnc(a,b) };

这在技术上是正确的,尤其是内联,但对我来说似乎是错误的。有没有其他更好的方法来实现这样的效果?

唯一的要求是作为参数传递的类型可能/将在某种程度上大于默认内存块大小,因此避免复制至关重要。也有一个非零的机会参数可以更小但也可以是一个右值。线程安全是可选的。

我考虑过对这些函数进行模板化,但在我看来,这在某种程度上也是错误的方法。模板解决了不同接受类型的问题。在我的情况下,类型是相同的,只是以不同的方式传递。

【问题讨论】:

标签: c++ parameter-passing c++14


【解决方案1】:

正如@SamVarshavchik 评论的那样,这是完美转发的常见候选者。一个简单的方法:

template<typename T, typename U>
void fnc(T&& a, U&& b)
{
    f(std::forward<T>(a));
    f(std::forward<U>(b));
}

如果用户传入不是largetype 类型的对象,则错误站点将在此函数中,这可能会使用户感到困惑。要将错误站点推送到调用者的代码中,我们可以使用 SFINAE 来约束参数类型:

template<
    typename T, typename U,
    typename = std::enable_if_t<
        std::is_same<std::decay_t<T>, largetype>{}
     && std::is_same<std::decay_t<U>, largetype>{}
    >
>
void fnc(T&& a, U&& b)
{
    f(std::forward<T>(a));
    f(std::forward<U>(b));
}

Online Demo

或者,您可能希望将错误站点保留在 fnc 内,但提供更清晰的错误消息 - 这可以通过 static_assert 完成:

template<typename T, typename U>
void fnc(T&& a, U&& b)
{
    static_assert(std::is_same<std::decay_t<T>, largetype>{},
                  "argument 'a' must be of type 'largetype'");
    static_assert(std::is_same<std::decay_t<U>, largetype>{},
                  "argument 'b' must be of type 'largetype'");

    f(std::forward<T>(a));
    f(std::forward<U>(b));
}

Online Demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-22
    • 2017-03-27
    • 2021-12-16
    • 2014-10-03
    • 1970-01-01
    • 2019-09-01
    • 1970-01-01
    • 2013-04-13
    相关资源
    最近更新 更多