C++ 可变模板与std::函数

C++ 可变模板与std::函数,c++,templates,c++14,variadic-templates,std-function,C++,Templates,C++14,Variadic Templates,Std Function,在以下代码中: #include <functional> #include <iostream> #include <tuple> template <typename... t> class a { public: explicit a(std::function<std::tuple<t...>()>&& p_d, std::function<bool(t...)

在以下代码中:

#include <functional>
#include <iostream>
#include <tuple>

template <typename... t>
class a {
 public:
  explicit a(std::function<std::tuple<t...>()>&& p_d,
             std::function<bool(t...)>&& p_f)
      : m_d(std::move(p_d)), m_f(std::move(p_f)) {}

  bool operator()() { return m_f(m_d()); }

 private:
  std::function<std::tuple<t...>()> m_d;
  std::function<bool(t...)> m_f;
};

class d {
  std::tuple<int, float, std::string&&> operator()() {
    return std::tuple<int, float, std::string&&>(-9, 3.14, "olá!");
  }
};

class f {
  bool operator()(int p_i, float p_f, std::string&& p_s) {
    std::cout << "i = " << p_i << ", f = " << p_f << ", s = " << p_s
              << std::endl;
    return true;
  }
};

int main() {
  d _d;
  f _f;
  typedef a<int, float, std::string&&> a_t;

  a_t _a(std::move(_d), std::move(_f));

  _a();

  return 0;
}
#包括
#包括
#包括
模板
甲级{
公众:
显式a(std::function&&p\d,
std::函数和p\f)
:mud(std::move(pud)),muf(std::move(puf)){
布尔运算符()({返回m_f(m_d());}
私人:
std::函数m_d;
std::函数m_f;
};
d类{
std::tuple运算符()(){
return std::tuple(-9,3.14,“olá!”);
}
};
f类{
布尔运算符()(int p_i,float p_f,std::string&&p_s){

std::cout我看到您的代码中至少有三个错误

没有特别的顺序

(1) 如果您想要一个函数,那么
操作符()
必须是
公共的
;您可以将它们都设置为
私有的

class d { // default for a class is private, so operator() is private
  std::tuple<int, float, std::string&&> operator()() {
    return std::tuple<int, float, std::string&&>(-9, 3.14, "olá!");
  }
};

class f { // default per a class is private, so operator() is private
  bool operator()(int p_i, float p_f, std::string&& p_s) {
    std::cout << "i = " << p_i << ", f = " << p_f << ", s = " << p_s
              << std::endl;
    return true;
  }
};
您可以使用

 std::tuple<int, float, std::string&&>(-9, 3.14, std::string{"olá!"});
工作

如果您确实希望在元组中引用
std::string
,则必须传递对对象的引用,该对象的生命周期足以覆盖元组的生命周期

(3)
d的
operator()
返回
std::tuple
,其中
f的
operator()
接受三个参数:a
int
、a
float
和a
std::string&

因此,您不能简单地将从第一个返回的值传递到第二个,而不解包
std::tuple
是一种方式,就像您在
a::operator()中所做的那样

您使用的是C++14,因此无法使用
std::apply()
(从C++17开始提供)

因此,您必须以某种方式模拟is(
std::make_index_sequence
std::index_sequence
std::get()
,等等)

以身作则

  bool operator() ()
   { return call(std::make_index_sequence<sizeof...(t)>{}); }

  template <std::size_t ... Is>
  auto call (std::index_sequence<Is...> const &)
   {
     auto tmp { m_d() }; // so m_d() is called only one time

     return m_f(static_cast<t>(std::get<Is>(tmp))...);
   }
bool运算符()()
{返回调用(std::make_index_sequence{});}
模板
自动调用(std::index\u sequence const&)
{
auto tmp{m_d()};//因此m_d()只被调用一次
返回m_f(static_cast(std::get(tmp))…);
}

<代码> >调用()/代码>可以是<代码>私下< //> > /p>关于(1),我只是错过了“f::PoprTror())和“d::操作程序())(……是私有的……(也是)初学者的错误!8)。我不知道(2),感谢信息。(3),主要问题是,为了保持与C++ 11的兼容性,我决定改为'BooF::操作程序()。(std::tuple&);(2)中的什么?你的立即泄漏?比如,永远不要写
*new X
@max66(2)是内存泄漏!这里没有动态分配的理由。
std::tuple(-9,3.14f,std::string{“olá!”;
作为
std::string{“olá!”完全有效
是一个R值。@Quimby…这是一个悬空引用。@Barry哦,你是对的。但是在这种情况下,
std::string&>(-9,3.14f,“olá!”);
也是悬空引用,对吗?因为在元组的构造函数中会有类似于
std::string&&member=“olá!”
这也会创建temp。无论其他问题如何,您的
d::operator()
都会悬空引用
字符串。
class d { // default for a class is private, so operator() is private
  std::tuple<int, float, std::string&&> operator()() {
    return std::tuple<int, float, std::string&&>(-9, 3.14, "olá!");
  }
};

class f { // default per a class is private, so operator() is private
  bool operator()(int p_i, float p_f, std::string&& p_s) {
    std::cout << "i = " << p_i << ", f = " << p_f << ", s = " << p_s
              << std::endl;
    return true;
  }
};
std::tuple<int, float, std::string>(-9, 3.14, "olá!");
bool operator()() { return m_f(m_d()); }
// ........................^^^^^^^^^^  Wrong!
bool operator()() { return std::apply(m_f, m_d()); }
// ........................^^^^^^^^^^^^^^^^^^^^^^  Starting from C++17
  bool operator() ()
   { return call(std::make_index_sequence<sizeof...(t)>{}); }

  template <std::size_t ... Is>
  auto call (std::index_sequence<Is...> const &)
   {
     auto tmp { m_d() }; // so m_d() is called only one time

     return m_f(static_cast<t>(std::get<Is>(tmp))...);
   }