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;
}
};
我想仅在notifyLoader()
存在的情况下致电loader->refresh()
。
我也使用void
作为默认类型,有没有更好的方法来做同样的事情?
答案 0 :(得分:2)
诀窍是一起使用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();
}
答案 1 :(得分:2)
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;
}
};
您可能希望通过提供调用notifyLoader()
的公开notifyLoader(0)
方法将其隐藏在您班级的公共界面中。
答案 2 :(得分:0)
我接受了答案,但我想评论我是如何实际做到的。
由于我不需要这个类TABLELOADER
,但是调用这个方法,我做了明确的模板专业化。
我同意它不完全是SFINAE并且它不会编译,如果我使用的类型没有loader->refresh()
且与std::nullptr_t
不同。
最后看起来如何:
(代码简化,可能有错误)
template<class TABLELOADER = std::nullptr_t>
class DiskFileFlush{
TABLELOADER *_loader;
public:
void process(){
// I want to call this,
// only if loader->refresh() exists.
notifyLoader(_loader);
}
template<class T>
static bool _notifyLoader(T *loader){
if (loader)
return loader->refresh();
return false;
}
static bool _notifyLoader(std::nullptr_t *){
return false;
}
};
答案 3 :(得分:0)
这是尽可能接近难以捉摸的$scope.dtOptions = DTOptionsBuilder.newOptions()
.withPaginationType('full_numbers')
.withDOM('frtip')
.withButtons([
'copy',
'print',
'excel'
]);
的最直接方式。
static_if(can_do_this)