Разве C++ не встроен полностью дополнительный?

Вы можете сделать это с версией монго выше 2.2

запрос, подобный этому:

db.coll.find({ 'notes.title': 'Hello MongoDB' }, {'notes. 

вы можете попробовать с $elemMatch как Джастин Дженкинс

: 1});

вы можете попробовать с $elemMatch как Джастин Дженкинс

20
задан Robert Gould 26 May 2009 в 03:37
поделиться

4 ответа

В самом деле, есть одно правило определения, в котором говорится, что встроенная функция должна быть определена в каждой используемой единице трансляции. Кровавые подробности следуют далее. Первый 3.2 / 3 :

Каждая программа должна содержать ровно одно определение каждой не встроенной функции или объекта, которые используются в этой программе; диагностика не требуется. Определение может явным образом присутствовать в программе, его можно найти в стандартной или пользовательской библиотеке или (при необходимости) оно определено неявно (см. 12.1, 12.4 и 12.8). Встроенная функция должна быть определена в каждой единице перевода, в которой она используется.

И, конечно же, 7.1.2 / 4 :

Встроенная функция должна быть определена в каждой единице перевода, в которой она используется и имеет одно и то же определение во всех случаях (3.2). [Примечание: вызов встроенной функции может встречаться до того, как ее определение появится в блоке перевода. ] Если функция с внешней связью объявлена ​​встроенной в одной единице перевода, она должна быть объявлена ​​встроенной во всех единицах перевода, в которых она появляется; Диагностика не требуется. Встроенная функция с внешней связью должна иметь один и тот же адрес во всех единицах трансляции. Статическая локальная переменная во встроенной функции extern всегда ссылается на один и тот же объект. Строковый литерал во встроенной функции extern - это один и тот же объект в разных единицах перевода.

Однако, если вы определяете свою функцию в определении класса, она неявно объявляется как встроенная функция. Это позволит вам многократно включать определение класса, содержащее это встроенное тело функции, в вашу программу. Поскольку функция имеет внешнюю связь, любое ее определение будет относиться к той же функции (или более кровавой - к той же сущности ).

Кровавые подробности о моем требовании. Первый 3.5 / 5 :

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

Затем ] 3.5 / 4 :

Имя, имеющее область пространства имен, имеет внешнюю связь, если это имя [...] именованного класса (пункт 9), или безымянный класс, определенный в объявлении typedef, в котором класс имеет имя typedef для целей связывания.

Это «имя для целей связывания» - это забавная вещь:

typedef struct { [...] } the_name;

Теперь у вас есть несколько определений одна и та же сущность в ваших программах, другая вещь ODR ограничивает вас. 3.2 / 5 следует за скучным материалом.

Может быть более одного определения типа класса (пункт 9), типа перечисления (7.2), встроенной функции с внешней связью (7.1.2) [ ...] в программе при условии, что каждое определение появляется в разных единицах перевода, и при условии, что определения удовлетворяют следующим требованиям. Если такой объект с именем D определен более чем в одной единице трансляции, то

  • каждое определение D должно состоять из одной и той же последовательности токенов; и
  • в каждом определении D соответствующие имена, найденные в соответствии с 3.4, должны относиться к объекту, определенному в определении D, или должны относиться к тому же объекту после разрешения перегрузки (13.3) и после сопоставления частичного специализация шаблона (14.8.3) [...]

Сейчас я убрал некоторые неважные вещи. Вышеупомянутые два важных вопроса о встроенных функциях следует помнить. Если вы определяете внешнюю встроенную функцию несколько раз, но определяете ее по-разному, или если вы определяете ее и имена, используемые в ней, разрешаются для разных сущностей, то вы выполняете неопределенное поведение.

Легко запомнить правило, согласно которому функция должна быть определена в каждом TU, в котором она используется. И то, что это то же самое, тоже легко запомнить. Но как насчет этой штуки с разрешением имен? Вот пример. Рассмотрим статическую функцию assert_it :

static void assert_it() { [...] }

Теперь, поскольку static предоставит ей внутреннюю связь, когда вы включаете ее в несколько единиц перевода, тогда каждое определение будет определять разные сущность . Это означает, что вам не разрешено использовать assert_it из внешней встроенной функции, которая будет определена в программе несколько раз: потому что происходит то, что встроенная функция будет ссылаться на одну объект, называемый assert_it в одном TU, но другой объект с тем же именем в другом TU. Вы обнаружите, что все это скучная теория, и компиляторы, вероятно, не будут жаловаться, но я обнаружил, что этот пример, в частности, показывает связь между ODR и объектами.


Далее следует возвращение к вашей конкретной проблеме.

Следующее - то же самое:

struct A { void f() { } };
struct A { inline void f(); }; void A::f() { } // same TU!

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

struct A { void f(); }; void A::f() { } // evil!

Теперь, если вы поместите inline в объявление f внутри класса, но затем опустите его определение в заголовке, тогда вы нарушите 3.2 / 3 7.1.2 / 4 , который говорит то же самое, только больше разработка), поскольку функция не определена в этой единице перевода!

Обратите внимание, что в C (C99) inline имеет другую семантику, чем в C ++. Если вы создаете внешнюю встроенную функцию, вам следует сначала прочитать хороший документ (желательно Стандарт), поскольку это действительно сложно в C (в основном, для любого используемого встроенного определения функции потребуется другое, не встроенное определение функции в другом ЕП. статические встроенные функции в C просты в обращении. Они ведут себя так же, как и любая другая функция, за исключением обычной подсказки о «встроенной подстановке». static inline как в C, так и в C ++ служит только подсказкой для встроенной замены. Поскольку static уже будет создавать другую сущность каждый раз, когда она используется (из-за внутренней связи), inline просто добавит подсказку inline-замены - не более того.

s используется (из-за внутренней связи), inline просто добавит подсказку inline-замены - не более того.

s используется (из-за внутренней связи), inline просто добавит подсказку inline-замены - не более того.

37
ответ дан 29 November 2019 в 23:04
поделиться

Независимо от того, является ли метод на самом деле встроенным, остается на усмотрение компилятора. Однако наличие ключевого слова inline также повлияет на связывание метода.

Связывание в C ++ - не моя специальность, поэтому я открою ссылки для лучшего объяснения.

В качестве альтернативы вы можете просто подождать litb , чтобы предоставить кровавые подробности примерно через час;)

10
ответ дан 29 November 2019 в 23:04
поделиться

Обратите внимание: когда метод объявлен встроенным, его определение ДОЛЖНО быть вместе с его объявлением.

6
ответ дан 29 November 2019 в 23:04
поделиться

Что касается ответа harshath.jr, метод не нужно объявлять встроенным, если в его определении есть ключевое слово "inline", и это определение доступно в том же заголовке, т.е. :

class foo
{
  void bar();
};

inline void foo::bar()
{
  ...
}

Это полезно для условного встраивания метода в зависимости от того, является ли сборка « debug » или « release » следующим образом:

// Header - foo.h

class foo
{
  void bar();  // Conditionally inlined.
};

#ifndef FOO_DEBUG
# include "foo.inl"
#endif

«Встроенный» файл мог бы выглядеть так:

// Inline Functions/Methods - foo.inl
#ifndef FOO_DEBUG
# define FOO_INLINE inline
#else
# define FOO_INLINE
#endif

FOO_INLINE void foo::bar()
{
  ...
}

, а реализации могло бы понравиться следующее:

// Implementation file - foo.cpp
#ifdef FOO_DEBUG
# include "foo.inl"
#endif

...

Это не совсем красиво, но у него есть применение, когда агрессивная инлайн-версия становится головной болью отладки.

2
ответ дан 29 November 2019 в 23:04
поделиться
Другие вопросы по тегам:

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