c++ - 基于可变参数函数参数调用类函数会导致错误

标签 c++ templates variadic-templates variadic-functions variadic

在使用以下带有可变数量参数的示例时遇到一些编译错误,并且需要一些帮助来找到一些解决方案或更好的方法。

我正在尝试根据下面提供的输入参数来初始化类变量,就像下面的示例一样,我愿意初始化“数据”类方法“select_area1_object”和“select_area2_object”,其中参数是可变的,但我愿意创建一些通用的方式,从主类中我只需要传递类型(在本例中是区域代码或任何其他输入参数)和它的参数,从主类传递的类型值应该决定调用哪个函数并基于此它应该初始化其可变数量的参数,请参见下面的示例。

#include <iostream>
#include <functional>
using namespace std;

enum area {AREA_1, AREA_2, AREA_3};

class data {
    public :
        int number;
        std::string name;
        std::string address;
        int area_code;
    
    template <typename type, typename... args>
    void create_object(type t, args&&... arg)
    {
        // here area1 or are2 methods should be called based on type & it should process variable arguments supplied from main.
        if(t == AREA_1)
        {
            select_area1_object(arg...);    
        }
        else if(t == AREA_2)
        {
            select_area2_object(arg...);
        }
    }
    
    void select_area1_object(int num, std::string nm, std::string ad)
    {
        number = num;
        name = nm;
        address = ad;
    }
    void select_area2_object(int num, std::string nm)
    {
        number = num;
        name = nm;
    }
};

// trying to create a common template here so that from the main I will not have to create an object and only need to worry about passing output arguments (like number, name, address).
template <typename type, typename... args>
void request_process(type t, args&&... arg)
{
    data d;
    d.create_object(t, std::forward<args>(arg)...);
}

int main()
{
    request_process(1, 1, "area1", "area1_address");
    request_process(2, 2, "area2");
    std::cout << "End of program" << endl;
}

看到以下错误:

tmp/858Sn1cFdf.cpp: In instantiation of 'void data::create_object(type, args&& ...) [with type = int; args = {int, const char (&)[6], const char (&)[14]}]':
/tmp/858Sn1cFdf.cpp:45:5:   required from 'void request_process(type, args&& ...) [with type = int; args = {int, const char (&)[6], const char (&)[14]}]'
/tmp/858Sn1cFdf.cpp:50:51:   required from here
/tmp/858Sn1cFdf.cpp:24:13: error: no matching function for call to 'data::select_area2_object(int&, const char [6], const char [14])'
   24 |             select_area2_object(arg...);
      |             ^~~~~~~~~~~~~~~~~~~
/tmp/858Sn1cFdf.cpp:34:10: note: candidate: 'void data::select_area2_object(int, std::string)'
   34 |     void select_area2_object(int num, std::string nm)
      |          ^~~~~~~~~~~~~~~~~~~
/tmp/858Sn1cFdf.cpp:34:10: note:   candidate expects 2 arguments, 3 provided
/tmp/858Sn1cFdf.cpp: In instantiation of 'void data::create_object(type, args&& ...) [with type = int; args = {int, const char (&)[6]}]':
/tmp/858Sn1cFdf.cpp:45:5:   required from 'void request_process(type, args&& ...) [with type = int; args = {int, const char (&)[6]}]'
/tmp/858Sn1cFdf.cpp:51:34:   required from here
/tmp/858Sn1cFdf.cpp:20:13: error: no matching function for call to 'data::select_area1_object(int&, const char [6])'
   20 |             select_area1_object(arg...);
      |             ^~~~~~~~~~~~~~~~~~~
/tmp/858Sn1cFdf.cpp:28:10: note: candidate: 'void data::select_area1_object(int, std::string, std::string)'
   28 |     void select_area1_object(int num, std::string nm, std::string ad)
      |          ^~~~~~~~~~~~~~~~~~~
/tmp/858Sn1cFdf.cpp:28:10: note:   **candidate expects 3 arguments, 2 provided**

如果我从类中删除 AREA2 功能,例如其方法、条件检查和从主“request_process(2, 2, “area2”);”调用它工作正常,所以我认为它不接受可变参数,在其他项目中尝试了同样的事情,但看到了相同的参数错误,并且我愿意基于此编写更多功能,其中参数会有所不同并且不想创建main 中的类对象,让模板处理类对象的创建和类方法的初始化。

请向我建议是否已经提供了一些解决方案,因为我没有发现描述的类似问题。

最佳答案

这与变量参数无关。 C++ 中的类型根本不能以这种方式工作。

如果您有 if (condition) { statements1 } else { statements2 },则 if 的两个分支都必须是类型正确的。

您的构造与此没有太大不同:

if (false) 
   std::cout << std::cos("hello, world");

如果这不起作用,那么你的也不起作用。但这是行不通的。

一种可能的解决方案是统一 select_area1_object、select_area2_object 以及您将来可能提出的任何其他 select_areaN_object 的接口(interface)。您可以让它们全部接受相同的 std::variant,在运行时检查传入的变体是否是它们期望的变体,如果不是,则提示并出错。

此 std::variant 的分支可以是原始 select_areaN_object 期望的参数元组。

另一个解决方案是使 t 成为非类型模板参数而不是普通函数参数,并执行 if constexpr 而不是常规if

关于c++ - 基于可变参数函数参数调用类函数会导致错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74528080/

相关文章:

c++ - 将 boost::function 与实例方法结合使用

c++ - 嵌套类中的 "Invalid covariant return type"错误,其方法返回基于模板的对象

c++ - 确保可变参数模板不包含重复项

c++ - 函数模板参数包不在参数列表的末尾

c++ - 为什么动态内存分配(堆)出现运行时错误?

c++ - GCC 的模板模板参数推导失败(适用于 MSVC)

c++ - 什么时候必须声明模板中使用的函数?

C++模板非类型参数lambda函数

c++ - 可变参数构造函数优先于用户提供的 move 构造函数,默认情况下除外

c++ - 使用 cmake 和 visual studio 2010 构建 yaml-cpp