c++ - 类模板实例化和通用引用

标签 c++ templates c++14 forwarding-reference

在这样的代码中:

template<class...> struct pack{};

template<class, class = int>
struct call_t
{
    template<class... args_t>
    static int apply(args_t&&...)
    { return 0; }
};

template<class... args_t>
struct call_t<pack<args_t...>, // (1)
        std::decay_t<decltype(convert(declval<args_t>()...))> >
{
    template<class... params_t> // (2)
    static int apply(params_t&&... args)
    { return convert(std::forward<params_t>(args)...); }
};

template<class... args_t>
auto test(args_t&&... args) // (3)
{
    return call_t<pack<args_t...> >::
       apply(std::forward<args_t>(args)...);
}

此函数根据函数 convert 向一个函数或另一个函数发送一组参数。存在并且可以使用传递的参数调用,保持完整(我猜)它们的确切传递类型,并且当它的返回类型是 int 时, 与引用或 const 限定符无关。

我对那段代码有3个疑惑。

  • (1) 是 declval返回类型仍然是通用引用吗?例如,declval<T>() , 与 T = int& , 它的返回类型是否为 int&& (真正的 r 值引用),或 int & &&并再次推导为int&传递给另一个调用时遵循通用引用的通常规则?我认为它没有(正如@101010 所指出的),但在那种情况下我不知道如何进行完美的过载测试。

  • (2) 我是否需要重新指定可变参数模板以使用通用引用推导规则,或者由于在 (3) 中已经推导了正确的类型,它们保持推导的类型不变?

或者我可以直接写

template<class... args_t>
struct call_t<pack<args_t...>, // (1)
        std::decay_t<decltype(convert(declval<args_t>()...))> >
{
    // (2)
    static int apply(args_t... args)
    { return convert(args...); }
};

?

call_t模板类是一个实现细节,因此,它只会在 test 内部被实例化.

最佳答案

这两种情况是等价的。这个例子:

template<class... args_t>
struct call_t<pack<args_t...>, // (1)
        std::decay_t<decltype(convert(declval<args_t>()...))> >
{
    // (2)
    static int apply(args_t... args)
    { return convert(args...); }
};

不转发任何东西。参数包args...是左值,因为它们有名字。这与这段代码非常不同:

template<class... params_t> // (2)
static int apply(params_t&&... args)
{ return convert(std::forward<params_t>(args)...); }

其中args... 转发。由此产生的行为是新示例可能比旧示例慢(执行复制而不是移动)或者可能会出人意料地无法编译。考虑 convert(std::unique_ptr<int> ) . 可以用 args_t = {std::unique_ptr<int>} 调用, 但内部 apply()会失败,因为您将尝试复制 unique_ptr .

你需要做的:

static int apply(args_t... args)
{ return convert(std::forward<args_t>(args)...); }

关于c++ - 类模板实例化和通用引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43334951/

相关文章:

c++ - 线程在 "in __lll_lock_wait"点卡住了几个线程

c++ - GNU C++ 如何检查 -std=c++0x 何时生效?

c++ - c++:使用数组,指针和循环来制作直方图。我就在那儿,我可能想得太辛苦了

c++ - typedef X<T>=T::UserType1,但如果不适用,typedef X<T>=UserType2

C++ eclipse 。抽象类不会编译

c++ - 如何用STL重构这段代码?

c++ - C++ 中的成员函数模板和重载 operator()

C++ 模板类继承[无法转换模板]

c++ - 在 C++ 中用一个 if 满足两个条件

c++ - 在没有分配器实例的情况下,是否有一种简单的方法在 C++ 中默认构造一个泛型类型?