【问题标题】:How to write function with parameter which type is deduced with 'auto' word?如何编写带有“自动”字推导类型的参数的函数?
【发布时间】:2019-01-10 18:08:17
【问题描述】:

我正在寻找一种干净的 c++11(直到 c++17)方法来编写一个函数,该函数只需使用给定的“开始”和“停止”时间(例如,给定间隔时间)将 fps 写入输出流. 所以我有这个代码,例如:

#include <iostream>
int main(int argc, char** argv) {
    typedef std::chrono::high_resolution_clock time_t;
    while (1) {
        auto start = time_t::now();

        // here is the call of function that do something
        // in this example will be printing
        std::cout << "Hello world!"

        auto stop = time_t::now();
        fsec_t duration = stop - start;

        double seconds = duration.count();
        double fps = (1.0 / seconds);

        std::stringstream s;
        s << "FPS: " << fps;

        std::cout << s.str();
    }
}

我想做类似的事情:

#include <iostream>

std::ostream & printFPS(std::ostream &stream, auto start);

int main(int argc, char** argv) {

    while (1) {
        auto start = std::chrono::high_resolution_clock::now();

        // here is the call of function that do something
        // in this example will be printing
        std::cout << "Hello world!"

        printFPS(std::cout, start);
    }
}

std::ostream & printFPS(std::ostream &stream, auto start){

    auto stop = std::chrono::high_resolution_clock::now();
    std::chrono::duration<float> duration = stop - start;

    double seconds = duration.count();
    double fps = (1.0 / seconds);

    std::stringstream s;
    s << "FPS: " << fps;

    return stream << s.str();
}

GCC 给了我提示'start'的推断类型是std::chrono::time_point&lt;std::chrono::_V2::system_clock, std::chrono::duration&lt;long int, std::ratio&lt;1, 1000000000&gt; &gt; &gt;,但我不想在函数中写这种类型(可能是推断会改变(?),而且它很长并且需要typedef) ,是否可以编写更优雅的函数,因为参数中不允许使用 auto ?谢谢!

【问题讨论】:

  • FYI time_t 对于时钟的类型来说是一个非常糟糕的选择。已经有一个类型,time_t,它代表一个时间单位(我很困惑阅读你的代码和看到time_t::now())。但是你用它来表示一个时钟,这是一个非常不同的东西。使用clock_t 之类的东西会好得多。
  • 另外,当我在这里时,使用 C++11 及更高版本,更喜欢 using 而不是 typedefusing clock_t = std::chrono::high_resolution_clock; 更容易阅读,因为你介绍的名字总是在左边,而你别名的东西总是在右边(而不是 typedef 给我们的有时在中间的乐趣)。
  • 哦,你是对的,它被添加为 main() 中的本地 typedef,只是为了提高可读性。我知道它可能会导致一些硬错误。感谢using clock_t = std::chrono::high_resolution_clock; 不知道这种语法

标签: c++ c++11 c++14 c++17


【解决方案1】:

您可以使用decltype推导出时间类型并将其用作参数的类型。

using time_type = decltype(std::chrono::high_resolution_clock::now());

std::ostream & printFPS(std::ostream &stream, time_type start);

【讨论】:

  • 这是规范的解决方案。尽管我个人质疑它的必要性;不仅返回类型不太可能以任何有意义的方式发生变化,而且如果发生变化,您可能了解它,以便检查所有用法。让类型系统为你工作;不要把它藏起来!
  • @LightnessRacesinOrbit 这取决于用例。如果您出于某种原因要求时钟为high_resolution_clock,则特别要求将其作为参数,但如果您只想使用与其他地方使用的时钟相同的时钟,这很好(尽管我认为模板函数可能更通用) .这个问题似乎暗示了第二种情况。 OP正在询问推断时钟类型。
  • @FrançoisAndrieux 我的观点是关于 [mis?] 在您不需要时使用类型推导的更广泛的观点,并且说类型推导失去了您的有用的接口更改通知。这是反 AAA 的论点。
【解决方案2】:

表达式std::chrono::high_resolution_clock::now() 返回一个std::chrono::high_resolution_clock::time_point 类型的值。所以你可以直接这样做:

std::ostream& printFPS(std::ostream&, std::chrono::high_resolution_clock::time_point );

但您的打印功能可能并不关心您从哪个时钟获得time_point它只关心它有一个time_point,因此您可以更一般地执行此操作:

template <typename Clock, typename Duration>
std::ostream& printFPS(std::ostream&, std::chrono::time_point<Clock, Duration> );

【讨论】:

  • 投反对票的人是否不赞成使用时钟的类型别名或函数模板?
【解决方案3】:

这是一个简单的模板声明案例(尽管 C++20 可能更容易并接受你的语法):

template<typename Duration>
std::ostream & printFPS(std::ostream &stream, Duration start);

然后定义:

template<typename Duration>
std::ostream & printFPS(std::ostream &stream, Duration start)
{}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多