模板函数根据类成员函数参数而有所不同

问题描述

层次结构中有两种类型的对象,但是它们都有一个我要调用的静态“查找”方法。第二个参数是对象的名称,第一个参数是容器。一些类具有在“数据库”中搜索的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,std::string>::value   // C++11
    << has_find_signature<ChildB,std::string>::value // C++11
;

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...