方法,该方法调用所有基类的同名方法(如果存在),并将返回值保存到列表中
method, that calls same-named method of all base classes, if exists and saves return value to a list
我正在编写一个宏,它生成助手方法来调用当前类的所有基类的所有同名方法,并跳过没有该名称方法的基类。(我没有发布实际的宏,因为我不想伤害任何人,下面是我的一个宏生成方法的测试文件)
我设法使它在不保留这些方法的返回值的情况下工作。现在我想保存这些值并返回一个列表。
下面是一个函数,由我的宏生成,它应该调用所有基的名为"base_method"的方法,以int和string作为参数。
我不明白,为什么我会得到错误(在代码下面)。
#include <type_traits>
#include <list>
#include <iostream>
namespace detail{
template <typename> struct sfinae_true : std::true_type{};
}
namespace detail{
template <typename T, typename A1, typename A2>
static auto test_base_method(int) ->
sfinae_true<decltype(std::declval<T>().base_method(std::declval<A1>(), std::declval<A2>()))>;
template <typename , typename A1, typename A2>
static auto test_base_method(long) ->
std::false_type;
template <typename T, typename A1, typename A2>
struct has_base_method : decltype(test_base_method<T, A1, A2>(0)){};
template <typename Base, typename T, std::enable_if_t<has_base_method<Base,int,std::string>::value, bool> = true >
auto call_base_method_if_any(T& obj, int arg1, std::string arg2) ->
decltype( obj.Base::base_method(std::declval<int>(), std::declval<std::string>()))
{
return obj.Base::base_method(arg1, arg2);
}
template <typename Base, typename T, std::enable_if_t<!has_base_method<Base,int,std::string>::value, bool> = false>
auto call_base_method_if_any(T&, int, std::string) -> bool
{
return false;
}
};
template <typename ... T>
class Z : public T ... {
public:
auto call_base_method_of_all_bases_if_any(int arg1, std::string arg2) -> std::list<bool> {
return std::list<bool> { ( detail::call_base_method_if_any<T>(*this, arg1, arg2)) ... };
}
};
struct A{
bool base_method(int, bool){ std::cout << "An"; return true; }
bool base_method_narg(){ std::cout << "A no argn"; return true; }
};
struct B{ void base_method(int, bool){ std::cout << "Bn"; } };
struct C{ void base_method(int a, std::string b){ std::cout << "C, int = " << a << ", string = " << b; } };
struct D{ };
int main(){
Z<A> b;
Z<A,B> c;
Z<A,B,C> d;
Z<A,B,C,D> a;
std::cout << "a:" << std::endl;
auto x =a.call_base_method_of_all_bases_if_any(0, "string");
std::cout << std::endl;
std::cout << "b:" << std::endl;
b.call_base_method_of_all_bases_if_any(0, "string");
std::cout << std::endl;
std::cout << "c:" << std::endl;
c.call_base_method_of_all_bases_if_any(0, "string");
std::cout << std::endl;
std::cout << "d:" << std::endl;
d.call_base_method_of_all_bases_if_any(0, "string");
std::cout << std::endl;
}
编译错误:
g++ --std=c++14 expression_sfinae.3.cpp
expression_sfinae.3.cpp: In instantiation of ‘std::__cxx11::list<bool> Z<T>::call_base_method_of_all_bases_if_any(int, std::__cxx11::string) [with T = {A, B, C, D}; std::__cxx11::string = std::__cxx11::basic_string<char>]’:
expression_sfinae.3.cpp:48:63: required from here
expression_sfinae.3.cpp:27:99: error: no matching function for call to ‘std::__cxx11::list<bool>::list(<brace-enclosed initializer list>)’
return std::list<bool> { ( detail::call_base_method_if_any<T>(*this, arg1, arg2)) ... };
^
In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/include/g++-v5/list:63:0,
from expression_sfinae.3.cpp:2:
/usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/include/g++-v5/bits/stl_list.h:697:9: note: candidate: template<class _InputIterator, class> std::__cxx11::list<_Tp, _Alloc>::list(_InputIterator, _InputIterator, const allocator_type&)
list(_InputIterator __first, _InputIterator __last,
^
/usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/include/g++-v5/bits/stl_list.h:697:9: note: template argument deduction/substitution failed:
expression_sfinae.3.cpp:27:74: note: cannot convert ‘detail::call_base_method_if_any<C, Z<A, B, C, D>, 1u>((*(Z<A, B, C, D>*)this), arg1, std::__cxx11::basic_string<char>(arg2))’ (type ‘void’) to type ‘const allocator_type& {aka const std::allocator<bool>&}’
return std::list<bool> { ( detail::call_base_method_if_any<T>(*this, arg1, arg2)) ... };
^
In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/include/g++-v5/list:63:0,
from expression_sfinae.3.cpp:2:
/usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/include/g++-v5/bits/stl_list.h:678:7: note: candidate: std::__cxx11::list<_Tp, _Alloc>::list(std::initializer_list<_Tp>, const allocator_type&) [with _Tp = bool; _Alloc = std::allocator<bool>; std::__cxx11::list<_Tp, _Alloc>::allocator_type = std::allocator<bool>]
list(initializer_list<value_type> __l,
^
/usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/include/g++-v5/bits/stl_list.h:678:7: note: candidate expects 2 arguments, 4 provided
/usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/include/g++-v5/bits/stl_list.h:667:7: note: candidate: std::__cxx11::list<_Tp, _Alloc>::list(std::__cxx11::list<_Tp, _Alloc>&&) [with _Tp = bool; _Alloc = std::allocator<bool>]
list(list&& __x) noexcept
^
u/5.3.0/include/g++-v5/bits/stl_list.h:697:9: note: template argument deduction/substitution failed:
expression_sfinae.3.cpp:27:74: note: cannot convert ‘detail::call_base_method_if_any<C, Z<A, B, C, D>, 1u>((*(Z<A, B, C, D>*)this), arg1, std::__cxx11::basic_string<char>(arg2))’ (type ‘void’) to type ‘const allocator_type& {aka const std::allocator<bool>&}’
return std::list<bool> { ( detail::call_base_method_if_any<T>(*this, arg1, arg2)) ... };
^
In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/include/g++-v5/list:63:0,
from expression_sfinae.3.cpp:2:
/usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/include/g++-v5/bits/stl_list.h:678:7: note: candidate: std::__cxx11::list<_Tp, _Alloc>::list(std::initializer_list<_Tp>, const allocator_type&) [with _Tp = bool; _Alloc = std::allocator<bool>; std::__cxx11::list<_Tp, _Alloc>::allocator_type = std::allocator<bool>]
list(initializer_list<value_type> __l,
^
/usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/include/g++-v5/bits/stl_list.h:678:7: note: candidate expects 2 arguments, 4 provided
/usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/include/g++-v5/bits/stl_list.h:667:7: note: candidate: std::__cxx11::list<_Tp, _Alloc>::list(std::__cxx11::list<_Tp, _Alloc>&&) [with _Tp = bool; _Alloc = std::allocator<bool>]
list(list&& __x) noexcept
^
// 9000 lines ommited
附言:我还没有弄清楚如何处理不返回任何内容的函数(我认为你不能有一个void列表)。欢迎提出任何建议。
C
的方法返回void
:
struct C {
void base_method(int a, std::string b);
^^^^^
};
您正试图使用该返回类型来构建您的std::list<bool>
。
假设你想排除这种情况,我会这样重写你的details
:
// 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);
}
相关文章:
- 获取从C++中同一类中的构造函数调用的方法返回的值
- 不能将方法返回的值用于另一个方法
- 方法错误"not all control paths return a value"和方法不返回值
- 对象引用中的字段以不同的方法返回不同的值
- 实例化对象并调用方法,使用单行语法在 C# 或 C++ 中返回值?
- 哪种返回值的方法在C++中效果更快?
- 使用新的c++返回值语法的Const方法
- 找不到使保证返回值优化工作的方法
- 在虚拟方法上返回值
- 为什么未调用具有常量参考返回值的超载方法
- 为循环中多次调用的函数返回值预分配内存的正确方法是什么
- 从 r 值引用限定方法返回 r 值引用是否是一种好的做法?
- C++ shared_ptr从派生方法返回此值
- 如何打印通过类方法返回的值
- 从函数捕获和初始化多个返回值的任何直接方法
- 返回值上的 C++ 方法链接不起作用
- C :不同类型的模板功能(方法)的自定义返回值
- 在从方法返回值中使用模板
- 使用方法返回值作为参数c++
- Turtle Mock: MOCK_EXPECT如果被Mock的类方法返回值则失败