Ожидается асинхронная функция Недба

Это связано с требованием отдельной компиляции и потому, что шаблоны являются полиморфизмом типа создания экземпляров.

Давайте немного приблизимся к конкретному для объяснения. Скажем, у меня есть следующие файлы:

  • foo.h объявляет интерфейс class MyClass<T>
  • foo.cpp определяет реализацию class MyClass<T>
  • bar.cpp использует MyClass<int>

. Отдельное средство компиляции. Я должен скомпилировать foo.cpp независимо от bar.cpp. Компилятор полностью выполняет всю сложную работу по анализу, оптимизации и генерации кода на каждом модуле компиляции; нам не нужно анализировать целую программу. Только компоновщик должен обрабатывать всю программу одновременно, и задача компоновщика значительно упрощается.

bar.cpp даже не нужно существовать при компиляции foo.cpp, но я все равно должен быть в состоянии связать foo.o Я уже имел вместе с bar.o Я только что выпустил, не перекомпилируя foo.cpp. foo.cpp может даже быть скомпилирован в динамическую библиотеку, распределенную где-то в другом месте без foo.cpp, и связан с кодом, который они пишут спустя годы после того, как я написал foo.cpp.

«Полиморфизм в стиле объектов» означает, что template MyClass<T> не является общим классом, который может быть скомпилирован в код, который может работать для любого значения T. Это добавит накладные расходы, такие как бокс, необходимо передать указатели на функции для распределителей и конструкторов и т. Д. Намерение шаблонов C ++ состоит в том, чтобы избежать необходимости писать почти идентичные class MyClass_int, class MyClass_float и т. Д., Но все же быть в состоянии закончить с компилируемым кодом, который в основном выглядит так, как если бы мы имели каждую версию отдельно. Таким образом, шаблон является буквально шаблоном; шаблон класса не класс, это рецепт создания нового класса для каждого T, с которым мы сталкиваемся. Шаблон не может быть скомпилирован в код, только результат создания экземпляра шаблона может быть скомпилирован.

Итак, когда foo.cpp скомпилирован, компилятор не может видеть bar.cpp, чтобы знать, что MyClass<int> необходимо. Он может видеть шаблон MyClass<T>, но он не может испускать код для этого (это шаблон, а не класс). И когда компилируется bar.cpp, компилятор может видеть, что ему нужно создать MyClass<int>, но он не может видеть шаблон MyClass<T> (только его интерфейс в foo.h), поэтому он не может его создать.

Если foo.cpp сам использует MyClass<int>, тогда код для него будет сгенерирован при компиляции foo.cpp, поэтому, когда bar.o связан с foo.o, они могут быть подключены и будут работать. Мы можем использовать этот факт, чтобы позволить конечный набор экземпляров шаблонов быть реализован в .cpp-файле, написав один шаблон. Но bar.cpp не может использовать шаблон в качестве шаблона и создавать его на всех типах, которые ему нравятся; он может использовать только ранее существовавшие версии шаблона, которые автор foo.cpp думал предоставить.

Вы можете подумать, что при компиляции шаблона компилятор должен «сгенерировать все версии», с теми, которые никогда не используются, отфильтровываются во время связывания. Помимо огромных накладных расходов и экстремальных трудностей, с которыми сталкивался такой подход, поскольку «модификаторы типа», такие как указатели и массивы, позволяют даже встроенным типам создавать бесконечное количество типов, что происходит, когда я расширяю свою программу добавив:

  • baz.cpp объявляет и реализует class BazPrivate и использует MyClass<BazPrivate>

Невозможно, чтобы это могло работать, если мы либо

  1. Необходимо перекомпилировать foo.cpp каждый раз, когда мы меняем любой другой файл в программе , в случае, если он добавил новый романный экземпляр MyClass<T>
  2. Требовать, чтобы baz.cpp содержал (возможно, через заголовок) полный шаблон MyClass<T>, чтобы компилятор мог генерировать MyClass<BazPrivate> во время компиляции baz.cpp.

Никто не любит (1), потому что системы компиляции целых программ принимают forever для компиляции и потому что это делает невозможным распространение компилированных библиотек без исходного кода. Итак, у нас есть (2).

-1
задан marc_s 3 March 2019 в 20:45
поделиться

1 ответ

Вам нужно поместить вызов res() внутри обратного вызова find. Немедленное выполнение обещания undefined не поможет.

Но вы действительно не должны проходить итеративный обратный вызов вообще. Вместо этого напишите

async function count() {
    let nedb = …;
    let count = 0;
    const pkgs = await query(nedb, {});
    pkgs.forEach(pkg => count++);
    // or maybe better just:
    const count = pkgs.length;
    console.log(count);
}

function query(pkgs, query) {
    return new Promise((resolve, reject)=> {
        pkgs.find(query).exec((error, result)=>{
            if (error !== null) reject(error);
            else resolve(result);
        });
    });
}
0
ответ дан Bergi 3 March 2019 в 20:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: