c++ - 模板函数取决于类成员函数参数
问题描述
层次结构中有两种类型的对象,但它们都有我要调用的静态“查找”方法。第二个参数是对象的名称,第一个是容器。一些类有一个在“数据库”中搜索的 find 方法(即,这是第一个参数),一些类有一个在该数据库的子容器中搜索的 find 方法,它本身就是这个层次结构中的一个类.
我想创建一个模板函数(好吧,或者它的一个 SFINAE 集),它可以根据它所拥有的 find 方法的签名来做正确的事情。我试图避免我的基本默认实现的旧的懒惰、令人满意的策略,并且即使它们是相同的替代实现类型,也不得不为其他情况考虑特殊情况。
老实说,这种 SFINAE 的东西有点让我头疼。我见过处理“有成员”情况的例子,但我认为我没有找到处理“有这个成员签名”和“有其他成员签名”之间分支的例子。所以它是一种三态,我猜,虽然我们不一定会遇到这样的情况,即使用一个根本没有该成员函数的类进行调用。
class Db;
class Obj { /*...*/ Db* getDb(); /*...*/ };
class Guts : public Obj { /*...*/ };
class Db : public Obj { /*...*/ Guts* getGuts(); /*...*/ };
class ChildA : public Obj { static ChildA* find(Db* db, const std::string& name); /*...*/ };
class ChildB : public Obj { static ChildB* find(Guts* dbg, const std::string& name); /*...*/ };
template <typename T>
bool findByName(Db* db, const std::string& name, T*& ret);
有什么提示或建议吗?对已经涵盖此主题的任何引用?C++11 版本更可取。
我认为我没有看到,并且很抱歉在这里需要手持的是如何使用与 SFINAE 相关的签名来表达 findByName 实现。我看到类似的问题,但我的小大脑无法在那里建立联系。;p
解决方案
如果您使用这些find
方法public
,您可以像这样测试签名:
#include <utility>
template<class T, class... Signature>
struct has_find_signature {
template<class> struct sfinae_true : std::true_type {};
// fake functions, only to be used in SFINAE context
template<class U>
static auto test_find(int) -> // returns a sfinae_true<> if SFINAE succeeds
sfinae_true<
// std::declval<U>(). could be just U:: since it's a static method
decltype( std::declval<U>().find( std::declval<Signature>()... ) )
>;
template<class U>
static auto test_find(long) -> std::false_type;
// decltype of a fake call to test_find() with an int to try the true_type (int)
// version first and only fall back on the false_type (long) version if SFINAE fails.
static constexpr bool value = decltype(test_find<T>(0))::value;
};
// Helper variable template (C++14 required):
template<class T, class... Signature>
constexpr bool has_find_signature_v = has_find_signature<T, Signature...>::value;
然后,您可以在其他模板或if constexpr
情况下使用它。
这将1001
在您的情况下打印:
std::cout
<< has_find_signature_v<ChildA, Db*, std::string> // C++14
<< has_find_signature_v<ChildA, Guts*, std::string> // C++14
<< has_find_signature<ChildB, Db*, std::string>::value // C++11
<< has_find_signature<ChildB, Guts*, std::string>::value // C++11
;
推荐阅读
- javascript - 在 html/js 中加密 src 的值
- python - 如何在python的where子句中使用变量来访问sql
- android - 在android中使用套接字发送和接收字符串
- python - 如果将光标悬停在小部件的特定区域上,则更改光标
- flutter - sms_autofill 无法检测到 OTP
- python - 如何在 Python 中找到以下问题的最小值?
- python - Tkinter 回调中的异常 - TypeError:字符串格式化期间并非所有参数都转换
- python - Python 流中的第一个非重复字符
- java - 集群标记显示不准确
- ansible - 如何在不更改 .rb 文件的情况下通过 Vagrantfile 扩展 vagrant 插件?