【问题标题】:Template argument deduction for initializer_list with forwarding带转发的 initializer_list 模板参数推导
【发布时间】:2019-02-21 10:04:26
【问题描述】:

我想使用性能。使用 initializer_list(大括号)转发,但我未能编写可编译的代码。

如何在下面的代码示例中进行类型推导?

#include <utility>

template <class _T> struct B {
    _T a;
    _T b; };

template <class _T> void bar(B<_T>&& a) {}

template <class _T> void bar(B<_T>& a) {}

template <class _T> struct A {
    template <class __T>
    void foo(__T&& a) {
        bar(std::forward<__T>(a));
    } };

int main() {
    A<int> a;
    a.foo({1, 3}); }

我知道可以使用可变参数模板参数进行完美转发,如下所示:

#include <utility>

template <class _T>
struct B {
    _T a;
    _T b;
};

template <class _T>
void bar(_T&& v1, _T&& v2) {
    B<_T> b{v1, v2};
}

template <class _T>
void bar(_T& v1, _T& v2) {
    B<_T> b{v1, v2};
}

template <class _T>
struct A {
    template <class... Args>
    void foo(Args&&... args) {
        bar(std::forward<Args>(args)...);
    }
};

int main() {
    A<int> a;
    a.foo(1, 3);
}

但我想用可爱的花括号打电话给foo

【问题讨论】:

  • 注意命名:保留包含__ 的名称。见keyword
  • 我猜你做不到。编译器将无法将{1, 3} 推断为initializer_list
  • ... 就像_T 这样的名字。

标签: c++ initializer-list perfect-forwarding


【解决方案1】:

{1, 3} 没有类型,因此不能推断为“通用”模板类型。

您可以使用 std::initializer_list 的重载来处理它;

template <class T>
struct A {
    template <class U>
    void foo(U&& a) {
        bar(std::forward<U>(a));
    }

    template <class U>
    void foo(std::initializer_list<U> a) {
        bar(a); // assuming bar(std::initializer_list<U>)
    }

};

int main() {
    A<int> a;
    a.foo({1, 3});
}

【讨论】:

    【解决方案2】:

    你不能。除了其他严重的缺点之外,std::initializer_list 不能通过简单地使用 {...} 语法来推断。

    a.foo(std::initializer_list{1, 3})
    

    将正确地传递推论,但您将无法使用它调用bar,因为您期望B 的实例。

    live example on wandbox.org


    怎么样

    a.foo(B<int>{1, 3})
    

    ?

    【讨论】:

      猜你喜欢
      • 2012-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-15
      相关资源
      最近更新 更多