时间:2019-05-01 标签:c++: variadic template and function overloading

标签 c++ variadic-functions overload-resolution

看下面的例子:https://onlinegdb.com/Hkg6iQ3ZNI

#include <iostream>
#include <utility>
#include <type_traits>

class A 
{
    public:
    A(int v=-10):v_(v){}
    void print()
    {
        std::cout << "called A: " << v_ << std::endl;
    }
    private:
    int v_;
};

void f(int v)
{
    std::cout << "called f: " << v << std::endl;
    
}


template<typename T,typename ... Args>
void run(A&& a,
         T&& t,
         Args&& ... args)
{
    a.print();
    t(std::forward<Args>(args)...);
}


template<typename T,typename ... Args>
void run(T&& t,
          Args&& ... args)
{
  run(A(),
      std::forward<T>(t),
      std::forward<Args>(args)...);
}

int main()
{
    int v_function=1;
    int v_a = 2;
    
    run(f,v_function);
    
    return 0;
}
上面的代码编译、运行和打印(如预期的那样):

called A: -10

called f: 1


但如果主函数修改为:
int main()
{
    int v_function=1;
    int v_a = 2;
    
    run(f,v_function);
    
    // !! added lines !!

    A a(v_a);
    run(a,f,v_function);
    
    return 0;
}
然后编译失败并出现错误:

main.cpp:30:6: error: no match for call to ‘(A) (void (&)(int), int&)’

t(std::forward(args)...);

~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~


这似乎表明即使 A 的实例作为第一个参数传递,重载函数
void(*)(T&&,Args&&...) 
被称为,而不是
void(*)(A&&,T&&,Args&&...) 

最佳答案


template<typename T,typename ... Args>
void run(A&& a,
         T&& t,
         Args&& ... args)
a不是转发引用,而是右值引用。这意味着当你做 run(a,f,v_function);该函数将不会被选中,因为 a是一个左值,不能绑定(bind)到右值引用。有两种快速方法可以解决此问题。首先,使用 std::movea
run(std::move(a),f,v_function);

但这不是很好。 a实际上并没有在函数中移动,所以你有点违反了最小惊喜原则。

第二个选项是使 A在函数中是模板类型,因此它成为转发引用,然后您可以将其限制为 A 类型像
template<typename A_, typename T,typename ... Args, std::enable_if_t<std::is_same_v<std::decay_t<A_>, A>, bool> = true>
void run(A_&& a,
         T&& t,
         Args&& ... args)
{
    a.print();
    t(std::forward<Args>(args)...);
}

关于时间:2019-05-01 标签:c++: variadic template and function overloading,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60383472/

相关文章:

postgresql - 如何将多行传递给 PostgreSQL 函数?

c# - C# 中的重载解析

c++ - 如果 `v` 是一个类,编译器可以将 `v + 1 - 1` 优化为 `v` 吗?

c++ - 当内存被其他对象使用时不要删除ptr

c - 如何将结构传递和访问 C 中的可变参数函数

c - 变量参数列表打印垃圾

c++ - "Ambiguous conversion sequence"- 这个概念的目的是什么?

c++ - 派生类的重载解析失败

c++ - Qt 复选框和单选按钮不显示

c++ - 如何获得C++或Qt中所有货币符号和货币缩写的数组?