Отдельная модель компиляции для библиотек, использующих шаблоны [duplicate]

Это означает, что указанная переменная не указана ни на что. Я мог бы сгенерировать это так:

SqlConnection connection = null;
connection.Open();

Это вызовет ошибку, потому что, пока я объявил переменную «connection», она не указала ни на что. Когда я пытаюсь вызвать член «Open», для его устранения нет ссылки, и он будет вызывать ошибку.

Чтобы избежать этой ошибки:

  1. Всегда инициализируйте свои объекты, прежде чем пытаться что-либо с ними делать.
  2. Если вы не уверены, что объект имеет значение null, проверьте его с помощью object == null.

Инструмент Resharper JetBrains определит каждое место в вашем коде, которое имеет возможность ошибки нулевой ссылки, позволяя вам ввести нулевую проверку. Эта ошибка является источником ошибок номер один, IMHO.

18
задан Jesper 3 May 2011 в 13:32
поделиться

5 ответов

Общий подход (как используется во многих библиотеках Boost, например) заключается в том, чтобы помещать помощника в пространство имен, называемое details, возможно, в отдельном заголовке (включенном в заголовок «public»).

Невозможно предотвратить его видимость и возможность вызова, но это довольно четко указывает, что это часть реализации, а не интерфейс.

20
ответ дан Mike Seymour 1 September 2018 в 10:34
поделиться

Установленный прецедент заключается в том, чтобы помещать такие вещи в специально (то есть последовательно) с именем вложенное пространство имен. Boost использует namespace details, Loki использует namespace Private. Очевидно, ничто не может помешать кому-либо использовать содержимое этих пространств имен, но оба названия передают смысл, что их содержимое не предназначено для общего потребления.

Как говорится, альтернативой является превращение func1 и func2 из шаблонов бесплатных функций в статические шаблоны функций-членов какого-либо общего класса; таким образом, helper может просто быть частным членом указанного класса, невидимым для внешнего мира:

struct funcs {
    template<typename T>
    static void func1(T const& value) {
        // ...
        helper(value);
    }

    template<typename T>
    static void func2(T const& value) {
        // ...
        helper(value);
    }

private:
    template<typename T>
    static void helper(T const& value) {
        // ...
    }
};
3
ответ дан ildjarn 1 September 2018 в 10:34
поделиться

Два варианта с головы:

  1. Переместите всю реализацию в файл hpp, который вы укажете в нижней части h-файла.
  2. Реорганируйте свой кода в качестве шаблонов классов, а затем сделать помощников конфиденциальными.
4
ответ дан nitsas 1 September 2018 в 10:34
поделиться

Я хотел бы (как было сказано ранее) создать класс шаблона, сделать все функции static и вспомогательной функцией приватными. Но кроме того, я также рекомендовал бы сделать конструктор закрытым, как показано ниже:

template <typename T>
class Foo{
public:
  static void func1(const T& value);
  static void func2(const T& value);
private:
  Foo();
  static void helper(const T& value);
}

Когда вы создадите конструктор private, компилятор не разрешит экземпляры этого шаблона. Таким образом, приведенный ниже код станет незаконным:

#include "foo.h"

int main(){
  int number = 0;
  Foo<int>::func1(number); //allowed
  Foo<int>::func2(number); //allowed
  Foo<int>::helper(number); //not allowed, because it's private
  Foo<int> foo_instance; //not allowed, because it's private
}

Так зачем кому-то это хотеть? Потому что наличие разных экземпляров, которые ТОЧНО, то же самое, чего вы, вероятно, никогда не захотите. Когда компилятор сообщает вам, что конструктор некоторого класса является закрытым, вы можете предположить, что наличие разных экземпляров этого файла будет неупорядоченным.

1
ответ дан user3635700 1 September 2018 в 10:34
поделиться

Поскольку пользователь вашего кода должен видеть полное определение функции func1, его реализация или реализация вспомогательной функции могут быть скрыты.

Но если вы переместите реализацию в еще один файл , пользователю будет только предъявлено объявление шаблона :

//templates.h
template< typename T > void f1( T& );

#include <templates_impl.h> // post-inclusion

И определение:

// templates_impl.h
template< typename T > void f1_helper( T& ) {
}

template< typename T > void f1( T& ) {
   // the function body
}
3
ответ дан xtofl 1 September 2018 в 10:34
поделиться
Другие вопросы по тегам:

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