Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.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++ 缓存函数结果,可能包括void_C++_Templates_C++14_Template Meta Programming - Fatal编程技术网

C++ 缓存函数结果,可能包括void

C++ 缓存函数结果,可能包括void,c++,templates,c++14,template-meta-programming,C++,Templates,C++14,Template Meta Programming,我有一个模板,其模板参数表示函数。该函数在模板中调用,函数的结果应存储,如下所示: template <class F> class C { F f; /* type see below */ cached; // ... somewhere ... cached = f(); }; 现在我在这个问题上花了整个下午的时间,并提出了以下解决方案。老实说,我怀疑这个问题是不常见的,所以没有一个标准的解决方案吗 [抱歉,太长了。最后给出了示例。] #in

我有一个模板,其模板参数表示函数。该函数在模板中调用,函数的结果应存储,如下所示:

template <class F>
class C {
   F f;
   /* type see below */ cached;

   // ... somewhere ...
       cached = f();
};
现在我在这个问题上花了整个下午的时间,并提出了以下解决方案。老实说,我怀疑这个问题是不常见的,所以没有一个标准的解决方案吗

[抱歉,太长了。最后给出了示例。]

#include <iostream>
#include <typeinfo>
#include <functional>

struct void_placeholder_t {};

// dummy type, since we do not want to overload comma for void_placeholder_t
struct void_replacer { };

// overload comma to return either t oder void_replacer {}
// (uses that if first argument is void, overload is not called)
template <class T>
constexpr decltype(auto) operator , (T && t, void_replacer) {
    return std::forward<T> (t);
}

//
// replace_void
// helper transforming a void_replacer into a void_placeholder_t
template <class T>
constexpr decltype(auto) replace_void (T && t) {
    return std::forward<T> (t);
}

constexpr void_placeholder_t replace_void (void_replacer) {
    return void_placeholder_t {};
}

//
// remove_rvalue_reference
//
template<class T> struct remove_rvalue_reference { using type = T; };
template<class T> struct remove_rvalue_reference<T &&> { using type = T; };
template <class T> using remove_rvalue_reference_t
    = typename remove_rvalue_reference<T>::type;

//
// result_after_void_replacement, result_after_void_replacement_t
//
template <class S> struct result_after_void_replacement;
template <class F, class ... Args>
struct result_after_void_replacement <F (Args ...)> {
    using type
        = remove_rvalue_reference_t < decltype (
            replace_void(
            ( std::declval<F> () (std::declval<Args> () ...),
            void_replacer {} ) )
        ) >;
};

template <class S>
using result_after_void_replacement_t = typename 
    result_after_void_replacement<S>::type;

//
// invoke_and_replace_void
//
template <class F, class ... Args>
constexpr result_after_void_replacement_t<F && (Args &&...)>
invoke_and_replace_void (F && f, Args && ... args)
{
    return replace_void(
    ( std::forward<F> (f) (std::forward<Args> (args) ...),
    void_replacer {} ) );
}

// example

void f(double) { }
double g(double d) { return d + 11.0; }

int main() {
    // conversion, without invoke_and_replace_void
    auto xf = replace_void ( (f(42.0), void_replacer {}) );
    std::cout << typeid(xf).name () << std::endl;
    auto xg = replace_void ( (g(42.0), void_replacer {}) );
    std::cout << typeid(xg).name () << " " << xg << std::endl;

    // conversion, with invoke_and_replace_void and no type deduction
    using F = void (double);
    result_after_void_replacement_t<F& (double)> zf = 
        invoke_and_replace_void (f, 42.0);
    std::cout << typeid(zf).name () << std::endl;

    using G = double (double);
    result_after_void_replacement_t<G& (double)> zg = 
        invoke_and_replace_void (g, 42.0);
    std::cout << typeid(zg).name () << " " << zg << std::endl;
    return 0;
}
#包括
#包括
#包括
结构void_占位符{};
//虚拟类型,因为我们不希望为void\u占位符\u t重载逗号
结构void_replacer{};
//重载逗号以返回命令void_replacer{}
//(如果第一个参数为void,则不调用重载)
模板
constexpr decltype(自动)运算符,(T&T,void\u replacer){
返回std::向前(t);
}
//
//替换无效
//将空\u替换符转换为空\u占位符\u t的帮助程序
模板
constexpr decltype(自动)替换\u void(T&&T){
返回std::向前(t);
}
constexpr void\u占位符\u t replace\u void(void\u replacer){
返回void_占位符_t{};
}
//
//删除右值引用
//
模板结构删除\u右值\u引用{using type=T;};
模板结构删除\u右值\u引用{using type=T;};
使用删除\u右值\u引用\u t的模板
=typename remove\u rvalue\u reference::type;
//
//无效替换后的结果,无效替换后的结果
//
替换后的模板结构结果;
模板
替换后的结构结果{
使用类型
=删除\u右值\u引用\u t;
};
模板
在\u void\u replacement\u t=typename之后使用result\u
替换后的结果::类型;
//
//调用并替换无效
//
模板
无效替换后的constexpr结果
调用和替换void(F&&F,Args&&…Args)
{
退换货无效(
(标准::转发(f)(标准::转发(args)…),
void_replacer{});
}
//范例
空f(双){}
双g(双d){返回d+11.0;}
int main(){
//转换,无需调用和替换
autoxf=replace_void((f(42.0),void_replacer{});

std::cout这应该适用于您的情况

template <class F, bool>
class C_helper{
public:
   F f;
   /* type see below */ cached;

   // ... somewhere ...
       cached = f();
};
template <class F>
class C_helper<F, true> {
public:
   F f;

   // ... somewhere ...
       f();
};

template <class F>
class C: public C_helper<F, std::is_void<std::result_of<F()>>::value> {
};
模板
类C_助手{
公众:
F;
/*键入以下内容*/cached;
//……某处。。。
cached=f();
};
模板
类C_助手{
公众:
F;
//……某处。。。
f();
};
模板
C类:公共C_助手{
};
这很好用:

template <typename Fn, typename RET, typename... Args >
struct Cache
{
    Cache( Fn f ) : _fn(f) {}
    const RET& operator()(Args ...args)
    {
        _cache = _fn( std::forward<Args>( args ) ... );
        return _cache;
    }
    Fn _fn;
    RET _cache;
};

template <typename Fn, typename... Args >
struct Cache< Fn, void, Args...>
{
    Cache( Fn f ) : _fn(f) {}
    void operator()(Args ...args)
    {
        _fn( std::forward<Args>( args ) ... );
    }
    Fn _fn;
};

template <typename Fn, typename... Args >
using C = Cache< Fn, typename std::result_of< Fn( Args... ) >::type, Args... >;

void f(double) { }
double g(double d) { return d + 11.0; }


C<decltype(&g), double> cache_g(g);
double res = cache_g( 1.0 );

C<decltype(&f), double> cache_f(f);
cache_f( 2.0 );
模板
结构缓存
{
缓存(Fn-f):\u-Fn(f){}
常量RET&运算符()(Args…Args)
{
_缓存=_fn(std::forward(args)…);
返回缓存;
}
Fn_Fn;
重新缓存;
};
模板
结构缓存
{
缓存(Fn-f):\u-Fn(f){}
void运算符()(Args…Args)
{
_fn(标准:正向(参数)…);
}
Fn_Fn;
};
模板
使用C=Cache::type,Args…>;
空f(双){}
双g(双d){返回d+11.0;}
C.g(g);
双分辨率=高速缓存(1.0);
C.f(f);
cache_f(2.0);
 >P>没有“C++标准中的某个东西”的标准解决方案。在2015年10月的会议上有一个尝试支持进化论工作组不喜欢的。


通常的方法是处理函数对象可能返回
void
,并且使用专门化处理值的情况。特别是当所讨论的函数模板相对复杂且公共部分不容易分解时,不幸的是,这种方法相当烦人。

常用的方法是create类
C
(或其部分)的专门化对于
void
type,这将不会存储返回值。嗯,事实上,这可能更容易。一种潜在的黑客方法:
typedef std::conditional\u t cached\u type;
cached\u type f;
。如果
f
返回void
f
将只是一个垃圾
int
变量。
f
应该只被调用吗一次?是的,我们可以假设。我在Bitbucket上放了一个改进的版本:。以防有人需要它。
template <typename Fn, typename RET, typename... Args >
struct Cache
{
    Cache( Fn f ) : _fn(f) {}
    const RET& operator()(Args ...args)
    {
        _cache = _fn( std::forward<Args>( args ) ... );
        return _cache;
    }
    Fn _fn;
    RET _cache;
};

template <typename Fn, typename... Args >
struct Cache< Fn, void, Args...>
{
    Cache( Fn f ) : _fn(f) {}
    void operator()(Args ...args)
    {
        _fn( std::forward<Args>( args ) ... );
    }
    Fn _fn;
};

template <typename Fn, typename... Args >
using C = Cache< Fn, typename std::result_of< Fn( Args... ) >::type, Args... >;

void f(double) { }
double g(double d) { return d + 11.0; }


C<decltype(&g), double> cache_g(g);
double res = cache_g( 1.0 );

C<decltype(&f), double> cache_f(f);
cache_f( 2.0 );