【问题标题】:How exactly should one use declttype to deduce the return type of a function which returns a class instance instantiated over template究竟应该如何使用 declttype 来推断函数的返回类型,该函数返回通过模板实例化的类实例
【发布时间】:2018-05-14 13:58:33
【问题描述】:

我们有一个添加 2 个浮点数的基本函数(达到一定的准确度)。

  float add(float x, float y)
  {
  std::cout << "\n in the add function \n";
  float res = x+y;
  std::cout << "\n exiting the add function \n";
  return res;
  }

我们有一个前向声明,

template <typename> struct Logger;

紧随其后,实施,

template<typename R, typename... Args>
struct Logger<R(Args...)>
{
    // these  would be members 
  function<R(Args...)> func; 
  string name;

   // this would be ctor 
  Logger(const function<R(Args...)>& func, const string& name)
    :
      func{func},
      name{name}
  {

  }
    // this would be the overload fun operator 
  R  operator() (Args ...args) const 
  {
    cout << "\n Entering Into ... .......\n" << name << endl; 
    R result = func(args...); //  this would be actual call to the basic      function 
    cout << "\n Exiting from  ...  \n" << name << endl; 
    return result; //  this would be of type R, the return from the function call

  }
};

然后我们有一个函数,

// This function would provide an instantiation of 
// the Logger class, 
// and that would call the ctor of the Logger class 
template <typename R, typename... Args>
auto make_logger(R (*func)(Args...), const string& name ) 
{
  return Logger<R(Args...)>{

    std::function<R(Args...)>(func),
    name
  };

}
// Notice, there is no decltype in the above function, and I would like to use 
// the decltype, I am aware that decltype cannot be used on packed template argument

//这里是API的使用,在一些main函数中

auto logger_add = make_logger(add, "**Adding Numbers**");
auto result = logger_add(2.0, 3.0);

问题:

可以使上述代码在 C++11 中工作吗?具体来说,使用declytype,如何使用make_logger函数。

注意事项: 我正在关注一本书,上面的代码取自, https://github.com/Apress/design-patterns-in-modern-cpp/blob/master/Structural/Decorator/decorator.cpp

【问题讨论】:

  • 为什么要在这里使用 decltype?你命名你返回的类型。
  • 我正在寻找 auto func() -> make_logger 函数的 int 类型语法
  • 所以...auto make_logger() -&gt; Logger&lt;R(Args...)&gt;。老实说,您甚至不需要尾随返回类型。

标签: c++ c++11 templates c++14 decltype


【解决方案1】:

您有一些拼写错误,导致您的代码无法同时使用 C++11 和 C++17 进行编译。该错字的结果是R 被推断为函数的类型而不是返回类型;)

修复:

template <typename R, typename... Args>
auto make_logger(R (*func)(Args...), const std::string& name )  -> Logger<R, Args...>
{
    return Logger<R, Args...> { std::function<R(Args...)>(func), name };
}

完整演示:http://coliru.stacked-crooked.com/a/3e9e5cf6d29669c4

【讨论】:

  • 你更改了类的签名,这是有效的。
【解决方案2】:

正如评论中所说,您已经提供了类型,所以它会是

template <typename R, typename... Args>
auto make_logger(R (*func)(Args...), const string& name ) 
-> Logger<R(Args...)>
{
  return { std::function<R(Args...)>(func), name };
}

Demo

就个人而言,我会写整个课程,例如:

template<typename F>
class Logger
{
private:
    F func; 
    std::string name;
public:
    Logger(const F& func, const std::string& name) :
      func{func},
      name{name}
    {}

    template <typename ... Args>    
    auto  operator() (Args&& ...args) const
    -> decltype(func(std::forward<Args>(args)...))
    {
        std::cout << "\n Entering Into ... .......\n" << name << std::endl;
        struct Finally {
            Finally(const std::string& name) : name(name) {}
            ~Finally() { std::cout << "\n Exiting from  ...  \n" << name << std::endl; }
            const std::string& name;
        } finally{name};
        return func(std::forward<Args>(args)...);
    }
};

template <typename F>
Logger<typename std::decay<F>::type>
make_logger(const F& func, const std::string& name)
{
  return { func, name };
}

Demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    • 1970-01-01
    • 2015-05-31
    • 1970-01-01
    相关资源
    最近更新 更多