C++ 方法,该方法调用所有基类的相同命名方法(如果存在),并将返回值保存到列表中

C++ 方法,该方法调用所有基类的相同命名方法(如果存在),并将返回值保存到列表中,c++,templates,c++14,variadic-templates,sfinae,C++,Templates,C++14,Variadic Templates,Sfinae,我正在编写一个宏,它生成helper方法来调用当前类的所有基类的所有相同命名方法,并跳过没有该名称的方法的基类。 (我没有发布实际的宏,因为我不想伤害任何人,下面是我的测试文件和一个宏生成的方法) 我设法让它在不保留这些方法的返回值的情况下工作。 现在我想保存这些值并返回一个列表 下面是一个函数,由我的宏生成,它应该调用所有基中名为“base_method”的方法,使用int和string作为参数 我不明白,为什么会出现错误(代码下面) #包括 #包括 #包括 名称空间详细信息{ 模板结构sfi

我正在编写一个宏,它生成helper方法来调用当前类的所有基类的所有相同命名方法,并跳过没有该名称的方法的基类。 (我没有发布实际的宏,因为我不想伤害任何人,下面是我的测试文件和一个宏生成的方法)

我设法让它在不保留这些方法的返回值的情况下工作。 现在我想保存这些值并返回一个列表

下面是一个函数,由我的宏生成,它应该调用所有基中名为“base_method”的方法,使用int和string作为参数

我不明白,为什么会出现错误(代码下面)

#包括
#包括
#包括
名称空间详细信息{
模板结构sfinae_true:std::true_type{};
}
名称空间详细信息{
模板
静态自动测试基础方法(int)->
斯菲娜·努特鲁尔;
模板
静态自动测试\u基本\u方法(长)->
std::假_型;
模板
结构具有_base_方法:decltype(test_base_方法(0)){};
模板
自动调用基本方法(如果有)(T&obj,int arg1,std::string arg2)->
decltype(obj.Base::Base_方法(std::declval(),std::declval())
{ 
返回obj.Base::Base_方法(arg1,arg2);
} 
模板=假>
自动调用基本方法(如果有)(T&,int,std::string)->bool
{ 
返回false;
} 
};
模板
Z类:公共交通。。。{
公众:
自动调用所有基础的方法(如果有)(int arg1,std::string arg2)->std::list{
返回std::list{(detail::call_base_method_,如果有(*this,arg1,arg2))…};
}
};
结构A{

bool base_方法(int,bool){std::cout问题的根本原因是
C
的方法返回
void

struct C {
    void base_method(int a, std::string b);
    ^^^^^
};
您正试图使用该返回类型来建立您的
std::list

假设您希望排除此案例,我将重写您的
详细信息,如下所示:

// this is the preferred overload (last argument is 'int' instead of '...')
// but will be SFINAE-d out if base_method() isn't callable with int or string
// or it returns something other than bool
template <class Base, class T,
    class = std::enable_if_t<std::is_same<bool,
        decltype(std::declval<Base&>().base_method(
            std::declval<int>(),
            std::declval<std::string>()))
        >::value>>
bool call_base_method_if_any_impl(T& obj, int arg1, std::string arg2, int)
{    
    return obj.Base::base_method(arg1, arg2);
}

// fallback overload
template <class Base, class T>
bool call_base_method_if_any_impl(T& obj, int arg1, std::string arg2, ...) {    
    return false;
}

template <class Base, class T>
bool call_base_method_if_any(T& obj, int arg1, std::string arg2) {
    return call_base_method_if_any_impl<Base>(obj, arg1, arg2, 0);
}
//这是首选重载(最后一个参数是“int”而不是“…”)
//但是如果base_method()不能用int或string调用,则将被SFINAE-d输出
//或者它返回的不是bool
模板
bool call_base_method_if_any_impl(T&obj,int arg1,std::string arg2,int)
{    
返回obj.Base::Base_方法(arg1,arg2);
}
//后备过载
模板
bool调用基本方法,如果有任何impl(T&obj,int arg1,std::string arg2,…){
返回false;
}
模板
bool call_base_method_如果有(T&obj,int arg1,std::string arg2){
如果有任何impl(obj,arg1,arg2,0),则返回call\u base\u method\u;
}

问题的根本原因是
C
的方法返回
void

struct C {
    void base_method(int a, std::string b);
    ^^^^^
};
您正试图使用该返回类型来建立您的
std::list

假设您希望排除此案例,我将重写您的
详细信息,如下所示:

// this is the preferred overload (last argument is 'int' instead of '...')
// but will be SFINAE-d out if base_method() isn't callable with int or string
// or it returns something other than bool
template <class Base, class T,
    class = std::enable_if_t<std::is_same<bool,
        decltype(std::declval<Base&>().base_method(
            std::declval<int>(),
            std::declval<std::string>()))
        >::value>>
bool call_base_method_if_any_impl(T& obj, int arg1, std::string arg2, int)
{    
    return obj.Base::base_method(arg1, arg2);
}

// fallback overload
template <class Base, class T>
bool call_base_method_if_any_impl(T& obj, int arg1, std::string arg2, ...) {    
    return false;
}

template <class Base, class T>
bool call_base_method_if_any(T& obj, int arg1, std::string arg2) {
    return call_base_method_if_any_impl<Base>(obj, arg1, arg2, 0);
}
//这是首选重载(最后一个参数是“int”而不是“…”)
//但是如果base_method()不能用int或string调用,则将被SFINAE-d输出
//或者它返回的不是bool
模板
bool call_base_method_if_any_impl(T&obj,int arg1,std::string arg2,int)
{    
返回obj.Base::Base_方法(arg1,arg2);
}
//后备过载
模板
bool调用基本方法,如果有任何impl(T&obj,int arg1,std::string arg2,…){
返回false;
}
模板
bool call_base_method_如果有(T&obj,int arg1,std::string arg2){
如果有任何impl(obj,arg1,arg2,0),则返回call\u base\u method\u;
}

cool。我仍然会尝试使用decltype作为返回值,因为在宏中,它应该支持不同的返回类型,您的更改可以挽救生命。不幸的是,您的解决方案仍然不适用于我。问题是它无法解决“如果不存在跳过方法”的问题部分。@Scottiger非常肯定。在您的示例中,没有一个类具有
bool base\u方法(int,string)
函数,并且
call\u base\u方法\u of_all\u basese\u if\u any()
正确返回包含
{false,false,false}的
列表
。是的,你是对的,但想法是跳过不存在的方法调用,而不是返回默认值。在我的初始示例中,就是这样。我当前结束了返回unique_ptr并检查它是否已设置,但我不喜欢。酷。我仍然会尝试使用decltype作为返回值,因为在宏中它应该是支持不同的返回类型,您的更改可以挽救生命。不幸的是,您的解决方案对我来说仍然不起作用。问题是它不能解决“如果不存在跳过方法”部分。@Scottiger非常确定它能解决。在您的示例中,没有一个类具有
bool base_方法(int,string)
函数和
调用\u all\u basese\u if\u any()的\u base\u方法\u
正确返回包含
{false,false,false}的
列表
。是的,你是对的,但我们的想法是跳过不存在的方法调用,而不是返回默认值。在我的初始示例中,就是这样。我目前结束了返回unique_ptr并检查它是否设置,但我不喜欢这样。