Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ c++;类指针中方法的SFINAE检查_C++_Sfinae - Fatal编程技术网

C++ c++;类指针中方法的SFINAE检查

C++ c++;类指针中方法的SFINAE检查,c++,sfinae,C++,Sfinae,我有这样的代码: template<class TABLELOADER = void> class DiskFileFlush{ TABLELOADER *_loader; public: void process(){ // I want to call this, // only if loader->refresh() exists. notifyLoader(); } bool notifyLoad

我有这样的代码:

template<class TABLELOADER = void>
class DiskFileFlush{
   TABLELOADER *_loader;

public:
   void process(){
       // I want to call this,
       // only if loader->refresh() exists.
       notifyLoader();
   }

    bool notifyLoader(){
        if (loader != nullptr)
            return loader->refresh();

        return false;
    }
};
模板
类DiskFileFlush{
表格加载器*\u加载器;
公众:
无效过程(){
//我想称之为,
//仅当loader->refresh()存在时。
notifyLoader();
}
bool notifyLoader(){
if(加载程序!=nullptr)
返回加载程序->刷新();
返回false;
}
};
仅当存在
loader->refresh()
时,我才想调用
notifyLoader()


我还使用了
void
作为默认类型,有没有更好的方法可以做到这一点?

诀窍是同时使用SFINAE和模板专门化

以下示例使用gcc 5.3编译:

#include <iostream>

template<typename T> struct has_refresh_operator
{
        //! Yes return value

        typedef char yes[1];

        //! No return value

        typedef char no[2];

        template<typename S>
        static yes &check(decltype( (*(S *)nullptr)->refresh()) *);

        template<typename S>
        static no &check(...);

        //! Determine whether the class implements ->refresh() method.

    static const bool value = sizeof(check<T>(0)) == sizeof(yes);
};

// Now, use a specialized template to figure out what to do:

template<bool> class invoke_refresh;

template<> class invoke_refresh<true> {
public:

    template<typename T>
    static inline auto doit(const T &t)
    {
        return t->refresh();
    }
};

template<> class invoke_refresh<false> {
public:
    template<typename T>
    static inline bool doit(const T &t)
    {
        return false;
    }
};

// Now, let's try some examples:

template<class TABLELOADER = void>
class DiskFileFlush{
   TABLELOADER *_loader;

public:

    DiskFileFlush(TABLELOADER *p) : _loader(p) {}

   void process(){
       // I want to call this,
       // only if loader->refresh() exists.
       notifyLoader();
   }

    bool notifyLoader(){
        if (_loader != nullptr)
            return invoke_refresh<has_refresh_operator<TABLELOADER *>::value>::doit(_loader);
        return false;
    }
};

// Try: class implements refresh(), class doesn't implement refresh(),
// and a void pointer.

class foo1 {

public:
    bool refresh()
    {
        std::cout << "Foo" << std::endl;
        return true;
    }
};

class foo2 {

public:
};

int main()
{
    foo1 bar1;
    foo2 bar2;

    DiskFileFlush<foo1> foobar1(&bar1);
    DiskFileFlush<foo2> foobar2(&bar2);
    DiskFileFlush<void> baz(0);

    foobar1.process();
    foobar2.process();
    baz.process();
}
#包括
模板结构具有\u刷新\u运算符
{
//!是返回值
typedef char yes[1];
//!没有返回值
typedef字符编号[2];
模板
静态是&检查(decltype((*(S*)nullptr)->refresh())*);
模板
静态无校验(…);
//!确定类是否实现->refresh()方法。
静态常量布尔值=sizeof(检查(0))==sizeof(是);
};
//现在,使用专门的模板确定要执行的操作:
模板类调用_刷新;
模板类调用\u刷新{
公众:
模板
静态内联自动doit(常量T&T)
{
返回t->refresh();
}
};
模板类调用\u刷新{
公众:
模板
静态内联bool doit(常数T&T)
{
返回false;
}
};
//现在,让我们尝试一些示例:
模板
类DiskFileFlush{
表格加载器*\u加载器;
公众:
DiskFileFlush(TABLELOADER*p):_loader(p){}
无效过程(){
//我想称之为,
//仅当loader->refresh()存在时。
notifyLoader();
}
bool notifyLoader(){
if(_loader!=nullptr)
返回invoke\u refresh::doit(\u loader);
返回false;
}
};
//Try:类实现refresh(),类不实现refresh(),
//和一个空指针。
foo1类{
公众:
bool刷新()
{

我接受了这个答案,但我想评论一下我是如何做到的

因为我什么都不需要这个类
TABLELOADER
,只需要调用这个方法,所以我进行了显式的模板专门化

我同意,如果我使用的类型没有
loader->refresh()
,并且与
std::nullptr\t
不同,那么它不完全是SFINAE,也不会编译

下面是结尾的样子:
(代码简化,可能有错误)

模板
类DiskFileFlush{
表格加载器*\u加载器;
公众:
无效过程(){
//我想称之为,
//仅当loader->refresh()存在时。
notifyLoader(_loader);
}
模板
静态bool\u notifyLoader(T*loader){
if(装载机)
返回加载程序->刷新();
返回false;
}
静态bool\u notifyLoader(std::nullptr\u t*){
返回false;
}
};

SFINAE现在可以以更简洁的方式完成,这要感谢表达式SFINAE:

template<class TABLELOADER = void>
class DiskFileFlush{
   TABLELOADER *_loader;

public:
   void process(){
       notifyLoader(0);
   }

    // Best match for the call above (0 is an int)
    template <class TL = TABLELOADER>
    auto notifyLoader(int) -> decltype(std::declval<TL&>().refresh()) {
        std::cout << "Refreshing!\n";

        if (_loader != nullptr)
            return _loader->refresh();

        return false;
    }

    // Fallback with low-priority varargs
    bool notifyLoader(...) {
        std::cout << "Not refreshing!\n";
        return false;
    }
};
模板
类DiskFileFlush{
表格加载器*\u加载器;
公众:
无效过程(){
通知加载器(0);
}
//上述调用的最佳匹配(0是整数)
模板
自动通知加载程序(int)->decltype(std::declval().refresh()){
std::cout refresh();
返回false;
}
//具有低优先级变量的回退
bool notifyLoader(…){

std::cout这是尽可能接近难以捉摸的
static\u的最直接的方法,如果(可以做到这一点)

// the if branch
template <typename T> 
    auto do_refresh (T* loader) -> decltype(
                                       loader->refresh(), // <-- "can_do_this" part
                                       bool())
    {
        loader->refresh();
        return false;
    };

// the else branch
template <typename T>
    auto do_refresh (...) -> bool
    {
        return false;
    }

bool refresh()
{
    return do_refresh(_loader);
}
//if分支
模板
自动刷新(T*加载器)->decltype(
加载程序->刷新(),//刷新();
返回false;
};
//埃尔斯分行
模板
自动刷新(…)->bool
{
返回false;
}
bool刷新()
{
返回do_刷新(_加载程序);
}

问题中的文本与显示的代码中的注释不匹配。“我想仅在notifyLoader()存在时调用notifyLoader()。-这是什么意思?搜索“SFINAE”在这个网站上有很多问题和答案,你可以处理。你没有例子,PosiSpress不是魔术。只是另一种类型。为什么代码> TabeleODRead */Cube应该与<代码> TabeleODADER < /C> >或<代码> TabeleloDe&或<代码> STD::向量< /代码>?是的。C++只是没有信誉。我不知道为什么。如果你已经在使用C++11,那么它可以更容易地实现为什么重新实现std::enable_If?好问题。我只是不知道如何使用enable_If来调用一个方法,只有在方法被实现的情况下,正如我所问的那样。也许有人可以发布一个更好、更短的答案。嗯,我很抱歉ry,如果在这里,你不需要std::enable_。我的错误。请看我的答案。
// the if branch
template <typename T> 
    auto do_refresh (T* loader) -> decltype(
                                       loader->refresh(), // <-- "can_do_this" part
                                       bool())
    {
        loader->refresh();
        return false;
    };

// the else branch
template <typename T>
    auto do_refresh (...) -> bool
    {
        return false;
    }

bool refresh()
{
    return do_refresh(_loader);
}