为什么需要在方法之间进行静态变量传递而不需要在同一个方法中?

时间:2018-02-18 03:47:46

标签: rust lifetime

我想在port提供的daomain()参数的函数中启动Hyper服务器,但该函数仅在我明确指出'static生命周期后才有效。这让我很困惑。

extern crate futures;
extern crate hyper;

use futures::future::Future;
use hyper::header::ContentLength;
use hyper::server::{Http, Request, Response, Service};
use std::net::SocketAddr;

trait Dao {}

struct MysqlDao;

impl Dao for MysqlDao {}

struct HelloWorld<'a> {
    dao: &'a Dao,
}

const PHRASE: &'static str = "Hello, World!";

impl<'a> Service for HelloWorld<'a> {
    type Request = Request;
    type Response = Response;
    type Error = hyper::Error;
    type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;

    fn call(&self, _req: Request) -> Self::Future {
        Box::new(futures::future::ok(
            Response::new()
                .with_header(ContentLength(PHRASE.len() as u64))
                .with_body(PHRASE),
        ))
    }
}

fn main() {
    let addr = "127.0.0.1:3000".parse().unwrap();
    let dao = MysqlDao;
    let server = Http::new()
        .bind(&addr, move || Ok(HelloWorld { dao: &dao }))
        .unwrap();
    server.run().unwrap();
}

Http::new().bind API文档说它需要NewService + 'static,所以我认为编译器会推断dao变体是'static,但是当我移动最后三个语句时出于主要原因,它无法推断!

fn main() {
    let addr = "127.0.0.1:3000".parse().unwrap();
    let dao: MysqlDao = MysqlDao;
    web_startup(&addr, &dao);
}

fn web_startup<T: Dao>(addr: &SocketAddr, dao: &T) {
    let server = Http::new()
        .bind(addr, move || Ok(HelloWorld { dao }))
        .unwrap();
    server.run().unwrap();
}

我收到错误:

error[E0477]: the type `[closure@src/main.rs:44:21: 44:51 dao:&T]` does not fulfill the required lifetime
  --> src/main.rs:44:10
   |
44 |         .bind(addr, move || Ok(HelloWorld { dao }))
   |          ^^^^
   |
   = note: type must satisfy the static lifetime

所以我修理了它:

fn main() {
    let addr = "127.0.0.1:3000".parse().unwrap();
    static DAO: MysqlDao = MysqlDao;
    web_startup(&addr, &DAO);
}

fn web_startup<T: Dao>(addr: &SocketAddr, dao: &'static T) {
    let server = Http::new()
        .bind(addr, move || Ok(HelloWorld { dao }))
        .unwrap();
    server.run().unwrap();
}

我不明白为什么我应该在static语句中使用static DAO: MysqlDao = MysqlDao;关键字,但在更改代码之前不需要。编译器无法推断它,或者我在不正确地思考问题?

1 个答案:

答案 0 :(得分:1)

编译器无法推断... GridView { anchors.fill: parent cellWidth: 100; cellHeight: 100 focus: true model: FileModel{ id: myModel folder: "/mnt/sdcard/app_pictureFrameImage" nameFilters: ["*.mp4","*.jpg"] } currentIndex: 0 highlight: Rectangle { width: 80; height: 80; color: "lightsteelblue" } delegate: Item { width: 100; height: 100 Image { id: myIcon y: 20; anchors.horizontalCenter: parent.horizontalCenter source: icon } Text { anchors { top: myIcon.bottom; horizontalCenter: parent.horizontalCenter } text: fileName } MouseArea { anchors.fill: parent onClicked: parent.GridView.view.currentIndex = index } } } ... 函数被调用它的唯一时间是#ifndef FILEMODEL_H #define FILEMODEL_H #include <QAbstractListModel> #include <QDirIterator> #include <QUrl> #include <QMetaType> #include <QFuture> #include <QtConcurrent/QtConcurrent> #include <iostream> using namespace std; struct File { Q_GADGET Q_PROPERTY(QString name MEMBER name) Q_PROPERTY(QUrl url MEMBER url) public: QString name; QUrl url; File(const QString& name=""){ this->name = QFileInfo(name).fileName(); this->url = QUrl::fromLocalFile(name); } }; Q_DECLARE_METATYPE(File) class FileModel : public QAbstractListModel { enum dashBoardRoles { NameRole=Qt::UserRole+1, URLRole }; Q_OBJECT Q_PROPERTY(QString folder READ folder WRITE setFolder NOTIFY folderChanged) Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters NOTIFY nameFiltersChanged) public: FileModel(QObject *parent=Q_NULLPTR):QAbstractListModel(parent){ } Q_INVOKABLE QVariant get(int index){ return QVariant::fromValue(m_all_dirs[index]); } int rowCount(const QModelIndex &parent=QModelIndex()) const{ Q_UNUSED(parent) return m_all_dirs.count(); } QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const{ if(index.row()<0 && index.row()>= rowCount()) return QVariant(); File file = m_all_dirs[index.row()]; if(role == NameRole) return file.name; else if(role == URLRole) return file.url; return QVariant(); } QHash<int, QByteArray> roleNames() const { QHash <int,QByteArray> roles; roles [NameRole]="fileName"; roles [URLRole]="url"; return roles; } QString folder() const{ return mFolder; } void setFolder(const QString &folder) { if(mFolder == folder) return; mFolder = folder; emit folderChanged(); findFiles(); } QStringList nameFilters() const{ return mNameFilters; } void setNameFilters(const QStringList &nameFilters){ if(mNameFilters == nameFilters) return; mNameFilters = nameFilters; emit nameFiltersChanged(); findFiles(); } signals: void folderChanged(); void nameFiltersChanged(); private: void findFiles(){ beginResetModel(); m_all_dirs.clear(); if(QDir(mFolder).exists()){ QFuture<QStringList> future = QtConcurrent::run([=]() { QStringList files; QDirIterator it(mFolder, mNameFilters, QDir::Files, QDirIterator::Subdirectories); while (it.hasNext()){ files<<it.next(); } return files; }); QStringList fullNames = future.result(); for(const QString& fullName: fullNames){ File file{fullName}; m_all_dirs << file; } } endResetModel(); } QString mFolder; QList<File> m_all_dirs; QStringList mNameFilters; }; #endif // FILEMODEL_H 调用的原因是因为无法保证。如果该功能是公开的并且它是由第三方模块调用的,该怎么办?编译器必须告诉最终用户在似乎需要的函数上使用web_startup。如果将来某个时间'static添加到Rust(例如REPL),那么即使您的私有函数也可以使用意外的函数参数调用,该怎么办?

你要求推断不应该发生。