首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++ SFINAE在引用类型和转换为引用的参数之间选择重载?

C++ SFINAE在引用类型和转换为引用的参数之间选择重载?
EN

Stack Overflow用户
提问于 2017-07-23 00:07:43
回答 1查看 212关注 0票数 0

考虑一下:

代码语言:javascript
复制
struct BigData {...};

// Let's get a BigData by reference, but use it as a value.
// For example, we may want to make a copy of the object, but we'd
// like to avoid the pass-by-value overhead at the call site.
template <typename T, *some template magic?*>
void processData(T& t) {
    printf("Your BigData was converted to a reference argument.\n");
    ...
}

// Now, we want an overload that will know that there wasn't a
// conversion to reference and will treat it like a reference.
// Perhaps we are adding this BigData to a list of references.
template <typename T, *some template magic?*>
void processData(T& t) {
    printf("You gave me a BigData reference.\n");
    ...
}

int main() {
    BigData data;
    BigData& ref = data;

    processData(data); // "Your BigData was converted to a reference argument."
    processData(ref); // "You gave me a BigData reference."

    return 0;
}

简而言之,我的目标是让重载区分引用绑定来自何处-要么是类型的值,要么是(已经)引用类型。我曾尝试将std::enable_if和family与不引用和不引用T的重载结合使用,但我找不到一种方法来实现这一点。任何帮助都是非常感谢的!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-07-23 00:15:48

我认为你没有理解引用绑定是如何工作的。您不仅可以将一个引用绑定到另一个引用,还可以绑定一个值类型的值(即不限定引用)

因此,如果希望通过引用传递BigData对象,只需执行以下操作

代码语言:javascript
复制
template <typename T>
void processData(T& t) {
    cout << "Your BigData was passed as a reference argument" << endl;
    // ...
}

int main() {
    BigData data;
    BigData& ref = data;

    processData(data); 
    processData(ref);

    return 0;
}

在这里,两个processData调用都将通过引用传递BigData对象(即在函数调用期间没有副本)。

当传递给函数的对象是独立于正常情况的引用时,您不需要处理这种情况。这里不需要std::enable_if

此外,没有办法区分这两种情况,使用dataref作为函数的参数,因为它们都是左值。如果要检查表达式的decltype是否为引用,则必须执行类似以下操作

代码语言:javascript
复制
#include <iostream>
#include <type_traits>

using std::cout;
using std::endl;

template <typename T, std::enable_if_t<std::is_reference<T>::value>* = nullptr>
void processData(std::add_lvalue_reference_t<T>) {
    cout << "You gave me a reference argument." << endl;
}

template <typename T, std::enable_if_t<!std::is_reference<T>::value>* = nullptr>
void processData(std::add_lvalue_reference_t<T>) {
    cout << "Your argument was converted to a reference." << endl;
}

int main() {
    auto integer_value = 1;
    const auto& integer_ref = 2;
    processData<decltype(integer_value)>(integer_value);
    processData<decltype(integer_ref)>(integer_ref);

    return 0;
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45256587

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档