如何在 C++ 中使用通用引用参数编写模板类的构造函数

2024-01-05

我有一个带有两个类型参数的 C++ 模板类 MyClass:

template <typename D, typename S>
struct MyClass {
private:
    D d_;
    S s_;
};

我想添加一个以 D 和 S 引用作为参数的构造函数,这样它就可以 推断 D 和 S:

template <typename D, typename S>
struct MyClass {
    // can bind to lvalues
    constexpr MyClass(const D &d, const S &s): d_(d), s_(s) {}

    // can bind to rvalues
    constexpr MyClass(D &&d, S &&s): d_(std::move(d)), s_(std::move(s)) {}

private:
    D d_;
    S s_;
};

效果很好。我可以从左值或右值创建对象:

auto c1 = MyClass(1, std::string("Hello"));    // rvalues

auto idx = 2;
auto msg = std::string("World");
auto c2 = MyClass(idx, msg);    // lvalues

但我只想要一个使用通用引用的构造函数而不是两个 每个都处理左值和右值。大概是这样的:

template <typename D, typename S>
struct MyClass {
    constexpr MyClass(D &&d, S &&s): d_(std::forward<D>(d)), s_(std::forward<S>(s)) {}
private:
    D d_;
    S s_;
};

它不适用于语句“auto w2 = MyClass(i, j);”。编译器抱怨

error: no viable constructor or deduction guide for deduction of template arguments of 'MyClass'
auto c2 = MyClass(idx, msg);    // lvalues
          ^
note: candidate function [with D = int, S = std::__1::basic_string<char>] not viable: no known conversion from 'int' to 'int &&' for
      1st argument
    constexpr MyClass(D &&d, S &&s): d_(std::forward<D>(d)), s_(std::forward<S>(s)) {}

命令行:c++ -std=c++17 test.cpp,编译为Apple clang version 12.0.0 (clang-1200.0.32.6)

看来构造函数只能接受右值。这不是通用参考。所以我的问题是我能实现通用参考样式构造函数? (我还想将 MyClass 保留为具有两个类型参数 D 和 S 的模板类。)


在这个片段中,d and s are NOT通用参考 - 它们是右值引用(因为 D 和 S 在类中已经由类实例化).

 template <typename D, typename S>
    struct MyClass {
        constexpr MyClass(D &&d, S &&s): d_(std::forward<D>(d)), s_(std::forward<S>(s)) {}
    private:
        D d_;
        S s_;
    };

根据斯科特·迈耶斯: https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers the 需要涉及类型推导对于类型变量D&& and S&& (并且仅以这种形式!)对于那些是通用引用,所以你需要额外的模板参数(所以类型是由类方法(=本例中的ctor)实例化):

template <typename D, typename S>
    struct MyClass {
        template <typename DD, typename SS>
        constexpr MyClass(DD &&d, SS &&s): d_(std::forward<DD>(d)), s_(std::forward<SS>(s)) {}
    private:
        D d_;
        S s_;
    };

通过构造函数调用启用类模板类型推导可以通过类模板推导指南来完成,例如:

template <typename DD, typename SS> MyClass(DD &&d, SS &&s) -> MyClass<DD, SS>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 C++ 中使用通用引用参数编写模板类的构造函数 的相关文章

随机推荐