Скрытые функции C++? [закрытый]

Я использовал jruby, в моем случае я создал в config / initializers

postgres_driver.rb

$CLASSPATH << '~/.rbenv/versions/jruby-1.7.17/lib/ruby/gems/shared/gems/jdbc-postgres-9.4.1200/lib/postgresql-9.4-1200.jdbc4.jar'

или везде, где ваш драйвер, и все!

114
задан 5 revs, 4 users 100% 9 September 2009 в 23:44
поделиться

64 ответа

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

Шаблонное метапрограммирование является едва скрытой функцией. Это находится даже в библиотеке повышения. См. MPL. Но если "почти скрытый" достаточно хорошо, то смотрите на библиотеки повышения . Это содержит много конфет, которые не являются легки доступный без поддержки сильной библиотеки.

Один пример библиотека boost.lambda , которая интересна, так как C++ не имеет функций лямбды в текущем стандарте.

Другой пример Loki, который "делает широкое применение шаблонного метапрограммирования C++ и реализует несколько наиболее часто используемых инструментов: список типов, функтор, одиночный элемент, интеллектуальный указатель, возражает фабрике, посетителю и мультиметодам". [ Википедия ]

6
ответ дан 2 revs, 2 users 84% 24 November 2019 в 02:28
поделиться

Нет никаких скрытых функций, но C++ языка очень мощен, и часто даже разработчики стандарта не могли вообразить то, для чего может использоваться C++.

На самом деле от достаточно простой конструкции языка можно записать что-то очень мощное. Много таких вещей доступно по www.boost.org как примеры (и http://www.boost.org/doc/libs/1_36_0/doc/html/lambda.html среди них).

Для понимания пути, как простой язык constuction может быть объединен к чему-то мощному, которое хорошо считать "Шаблоны C++: полное руководство" David Vandevoorde, Nicolai M. Josuttis и действительно волшебная книга "современный Дизайн C++..." Andrei Alexandrescu .

И наконец, трудно изучить C++, необходимо попытаться заполнить его;)

5
ответ дан sergtk 24 November 2019 в 02:28
поделиться

Я не уверен в скрытом, но существуют [приблизительно 110] интересные 'приемы' , которые, вероятно, не очевидны из просто чтения спецификации.

3
ответ дан dbrien 24 November 2019 в 02:28
поделиться

Большинство разработчиков C++ игнорирует питание шаблонного метапрограммирования. Выезд Loki Libary . Это реализует несколько усовершенствованных инструментов как список типов, функтор, одиночный элемент, интеллектуальный указатель, объектная фабрика, посетитель и шаблонное метапрограммирование использования мультиметодов экстенсивно (от Википедия ). Для большей части части Вы могли рассмотреть их как "скрытую" функцию C++.

3
ответ дан Sridhar Iyer 24 November 2019 в 02:28
поделиться
  • указатели на методы класса
  • ключевое слово
"имени типа"
3
ответ дан shoosh 24 November 2019 в 02:28
поделиться

Существует большое "неопределенное поведение". Можно изучить, как избежать их читающий хорошие книги и читающий стандарты.

3
ответ дан 2 revs, 2 users 50% 24 November 2019 в 02:28
поделиться

От Истины C++ .

функции Определения, имеющие идентичные подписи в том же объеме, таким образом, это законно:

template<class T> // (a) a base template
void f(T) {
  std::cout << "f(T)\n";
}

template<>
void f<>(int*) { // (b) an explicit specialization
  std::cout << "f(int *) specilization\n";
}

template<class T> // (c) another, overloads (a)
void f(T*) {
  std::cout << "f(T *)\n";
}

template<>
void f<>(int*) { // (d) another identical explicit specialization
  std::cout << "f(int *) another specilization\n";
}
3
ответ дан 2 revs, 2 users 62% 24 November 2019 в 02:28
поделиться

Существуют тонны "хитрых" конструкций в C++. Они идут от "простого" implementions изолированные/окончательные классы использующее виртуальное наследование. И доберитесь до "довольно сложных" конструкций метапрограммирования, таких как Повышение MPL ( учебное руководство ). Возможности для стрельбы в себя в ноге бесконечны, но, если контролируется (т.е. закаленные программисты), обеспечьте часть лучшей гибкости с точки зрения пригодности для обслуживания и производительности.

1
ответ дан Amir 24 November 2019 в 02:28
поделиться

Если оператор удаляет (), берет аргумент размера в дополнение к *пусто, который означает, что это, высоко, будет базовый класс. Тот аргумент размера представляет возможную проверку размера типов для уничтожения корректного. Здесь, что Stephen Dewhurst говорит об этом:

Уведомление также, что мы использовали версию с двумя аргументами оператора, удаляет, а не обычная версия с одним аргументом. Эта версия с двумя аргументами является другой "обычной" версией членского оператора, часто удаляют используемый базовыми классами, которые ожидают, что производные классы для наследования их оператора удаляют реализацию. Второй аргумент будет содержать размер объекта, являющегося deleted— информация, которая часто полезна в реализации пользовательского управления памятью.

1
ответ дан Özgür 24 November 2019 в 02:28
поделиться
class Empty {};

namespace std {
  // #1 specializing from std namespace is okay under certain circumstances
  template<>
  void swap<Empty>(Empty&, Empty&) {} 
}

/* #2 The following function has no arguments. 
   There is no 'unknown argument list' as we do
   in C.
*/
void my_function() { 
  cout << "whoa! an error\n"; // #3 using can be scoped, as it is in main below
  // and this doesn't affect things outside of that scope
}

int main() {
  using namespace std; /* #4 you can use using in function scopes */
  cout << sizeof(Empty) << "\n"; /* #5 sizeof(Empty) is never 0 */
  /* #6 falling off of main without an explicit return means "return 0;" */
}
0
ответ дан 5 revs, 2 users 73% 24 November 2019 в 02:28
поделиться

Адресная арифметика с указателями.

Это - на самом деле функция C, но я заметил, что немного людей, которые используют C/C++, действительно знают, что это даже существует. Я полагаю, что эта функция языка C действительно показывает гению и видению его изобретателя.

, Короче говоря, адресная арифметика с указателями позволяет компилятору работать [n] как * (a+n) для любого типа a. Как примечание стороны, как '+' коммутативный [n], конечно, эквивалентно n.

-2
ответ дан bernardn 24 November 2019 в 02:28
поделиться

Опасный секрет

Fred* f = new(ram) Fred(); http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.10
f->~Fred();

Мой любимый секрет, который я редко вижу используемый:

class A
{
};

struct B
{
  A a;
  operator A&() { return a; }
};

void func(A a) { }

int main()
{
  A a, c;
  B b;
  a=c;
  func(b); //yeah baby
  a=b; //gotta love this
}
8
ответ дан 3 revs, 3 users 84%user34537 24 November 2019 в 02:28
поделиться

Я нашел, что этот блог был удивительным ресурсом о arcanes C++: Истины C++ .

9
ответ дан 2 revs, 2 users 86% 24 November 2019 в 02:28
поделиться

Косвенная идиома преобразования:

Предположим, что Вы разрабатываете класс интеллектуального указателя. В дополнение к перегрузке операторов * и->, класс интеллектуального указателя обычно определяет оператор преобразования к bool:

template <class T>
class Ptr
{
public:
 operator bool() const
 {
  return (rawptr ? true: false);
 }
//..more stuff
private:
 T * rawptr;
};

Преобразование в bool позволяет клиентам использовать интеллектуальные указатели в выражениях, которые требуют bool операндов:

Ptr<int> ptr(new int);
if(ptr ) //calls operator bool()
 cout<<"int value is: "<<*ptr <<endl;
else
 cout<<"empty"<<endl;

Кроме того, неявное преобразование в bool требуется в условных объявлениях, таких как:

if (shared_ptr<X> px = dynamic_pointer_cast<X>(py))
{
 //we get here only of px isn't empty
} 

Увы, это автоматическое преобразование открывает логический элемент для нежелательных неожиданностей:

Ptr <int> p1;
Ptr <double> p2;

//surprise #1
cout<<"p1 + p2 = "<< p1+p2 <<endl; 
//prints 0, 1, or 2, although there isn't an overloaded operator+()

Ptr <File> pf;
Ptr <Query> pq; // Query and File are unrelated 

//surprise #2
if(pf==pq) //compares bool values, not pointers! 

Решение: Используйте "косвенное преобразование" идиома преобразованием от указателя до элемента данных [pMember] к bool так, чтобы было только 1 неявное преобразование, которое предотвратит вышеупомянутое неожиданное поведение: pMember-> bool скорее, что bool-> что-то еще.

1
ответ дан Özgür 24 November 2019 в 02:28
поделиться

Обратите внимание на различие между бесплатными инициализациями указателя указателя функции и функции членства:

функция членства:

struct S
{
 void func(){};
};
int main(){
void (S::*pmf)()=&S::func;//  & is mandatory
}

и бесплатная функция:

void func(int){}
int main(){
void (*pf)(int)=func; // & is unnecessary it can be &func as well; 
}

Благодаря этому избыточному и, можно добавить потоковые манипуляторы - которые являются бесплатными функциями - в цепочке без него:

cout<<hex<<56; //otherwise you would have to write cout<<&hex<<56, not neat.
2
ответ дан Özgür 24 November 2019 в 02:28
поделиться

Эмуляция переинтерпретации броска с статическим приведением :

int var;
string *str = reinterpret_cast<string*>(&var);

выше код эквивалентен следующему:

int var;    
string *str = static_cast<string*>(static_cast<void*>(&var));
-1
ответ дан 2 revs 24 November 2019 в 02:28
поделиться

Класс и структура class-keys почти идентичны. Основное отличие состоит в том, что классы по умолчанию имеют частный доступ для членов и баз, а структуры по умолчанию - открытый:

// this is completely valid C++:
class A;
struct A { virtual ~A() = 0; };
class B : public A { public: virtual ~B(); };

// means the exact same as:
struct A;
class A { public: virtual ~A() = 0; };
struct B : A { virtual ~B(); };

// you can't even tell the difference from other code whether 'struct'
// or 'class' was used for A and B

Союзы также могут иметь члены и методы и по умолчанию имеют общий доступ аналогично структурам.

1
ответ дан 24 November 2019 в 02:28
поделиться

Добавление ограничений в шаблоны.

0
ответ дан 24 November 2019 в 02:28
поделиться

У примитивных типов есть конструкторы.

int i(3);

работает.

7
ответ дан 24 November 2019 в 02:28
поделиться

Мне кажется, что лишь немногие люди знают о безымянных пространствах имен:

namespace {
  // Classes, functions, and objects here.
}

Безымянные пространства имен ведут себя так, как если бы они были заменены на:

namespace __unique_name__ { /* empty body */ }
using namespace __unique_name__;
namespace __unique_name__ {
  // original namespace body
}

".. где все вхождения [это уникальное имя ] в единице перевода заменяются тем же идентификатором, и этот идентификатор отличается от всех других идентификаторов во всей программе ». [C ++ 03, 7.3.1.1/1]

4
ответ дан 24 November 2019 в 02:28
поделиться

Для потомков, вот сообщение на форуме, Адриан связано с:

В VC # Express это свойство отсутствует, но вы все равно можете создать конфигурация x86, если вы знаете куда посмотрите.

Похоже, длинный список шагов, но как только вы узнаете, где эти вещи это намного проще. Все, кто только есть VC # Express наверняка найдет это полезно. Как только вы узнаете о Configuration Manager, это будет много более интуитивно понятным в следующий раз.

  1. В VC # Express 2005 перейдите в Инструменты -> Параметры.
  2. В нижнем левом углу диалогового окна Параметры установите флажок, говорит: «Показать все настройки».
  3. В древовидной структуре слева выберите «Проекты и решения».
  4. В параметрах справа установите флажок «Показать дополнительные конфигурации сборки. "
  5. Нажмите OK.
  6. Перейдите в Build -> Configuration Manager ...
  7. В столбце Platform рядом с вашим проектом щелкните поле со списком и выберите «».
  8. В настройке «Новая платформа» выберите «x86».
  9. Нажмите OK.
  10. Нажмите «Закрыть».

Теперь у вас есть x86 конфигурация! Проще простого! : -)

Также рекомендую использовать Configuration Менеджер по удалению любого процессора Платформа. Вы действительно этого не хотите если у вас когда-нибудь возникнет зависимость от 32-битной собственные библиотеки DLL (даже косвенные ( ) из javascript

var f = A.e
f.call(a) 

Для участников это немного похоже на доступ с помощью оператора []

a['d']
0
ответ дан 24 November 2019 в 02:28
поделиться
3
ответ дан 24 November 2019 в 02:28
поделиться

Я считаю, что создание рекурсивных шаблонов довольно круто:

template<class int>
class foo;

template
class foo<0> {
    int* get<0>() { return array; }
    int* array;  
};

template<class int>
class foo<i> : public foo<i-1> {
    int* get<i>() { return array + 1; }  
};

Я использовал это для создания класса с 10-15 функциями, которые возвращают указатели на различные части массива, так как API, который я использовал требовался один указатель на функцию для каждого значения.

То есть программирование компилятора для генерации группы функций с помощью рекурсии. Проще простого. :)

1
ответ дан 24 November 2019 в 02:28
поделиться

main () не требует возвращаемого значения:

int main(){}

- самая короткая допустимая программа на C ++.

2
ответ дан 24 November 2019 в 02:28
поделиться

Мой любимый (на данный момент) момент - это отсутствие сематики в таком утверждении, как A=B=C. То, что значение A в основном неопределено.

Подумайте об этом:

class clC
{
public:
   clC& operator=(const clC& other)
   {
      //do some assignment stuff
      return copy(other);
   }
   virtual clC& copy(const clC& other);
}

class clB : public clC
{
public:
  clB() : m_copy()
  {
  }

  clC& copy(const clC& other)
  {
    return m_copy;
  }

private:
  class clInnerB : public clC
  {
  }
  clInnerB m_copy;
}

теперь A может быть типом, недоступным никаким другим объектам, кроме объектов типа clB, и иметь значение, не имеющее отношения к C.

.
0
ответ дан 24 November 2019 в 02:28
поделиться
  1. map :: insert (std :: pair (key, value)); не перезаписывается, если значение ключа уже существует.

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

     class MyClass {public: / * code * /} myClass; 
     
2
ответ дан 24 November 2019 в 02:28
поделиться

Вы можете просматривать все предопределенные макросы с помощью переключателей командной строки с некоторыми компиляторами. Это работает с gcc и icc (компилятор Intel C ++):

$ touch empty.cpp
$ g++ -E -dM empty.cpp | sort >gxx-macros.txt
$ icc -E -dM empty.cpp | sort >icx-macros.txt
$ touch empty.c
$ gcc -E -dM empty.c | sort >gcc-macros.txt
$ icc -E -dM empty.c | sort >icc-macros.txt

Для MSVC они перечислены в единственном месте . Они могут быть задокументированы в одном месте и для других, но с помощью приведенных выше команд вы можете ясно увидеть , что определено, а что нет, и какие именно значения используются после применения всех остальных команд линейные переключатели.

Сравните (после сортировки):

 $ diff gxx-macros.txt icx-macros.txt
 $ diff gxx-macros.txt gcc-macros.txt
 $ diff icx-macros.txt icc-macros.txt
0
ответ дан 24 November 2019 в 02:28
поделиться

Локальные классы - это круто :

struct MyAwesomeAbstractClass
{ ... };


template <typename T>
MyAwesomeAbstractClass*
create_awesome(T param)
{
    struct ans : MyAwesomeAbstractClass
    {
        // Make the implementation depend on T
    };

    return new ans(...);
}

довольно аккуратно, поскольку не загрязняет пространство имен бесполезными определениями классов...

8
ответ дан 24 November 2019 в 02:28
поделиться

Одна скрытая возможность, скрытая даже для разработчиков GCC, заключается в инициализации члена массива с помощью строкового литерала. Предположим, у вас есть структура, которая должна работать с массивом C, и вы хотите инициализировать член массива содержимым по умолчанию

struct Person {
  char name[255];
  Person():name("???") { }
};

Это работает, и работает только с массивами char и инициализаторами строкового литерала. Никакого strcpy не требуется!

7
ответ дан 24 November 2019 в 02:28
поделиться