При запуске doxywizard
из искателя он использует глобально заданный путь, а не путь, заданный в $HOME/.bashrc
. Таким образом, существует ряд решений, включая добавление /usr/local/bin
и др. К глобальному пути (/etc/bashrc
) или создание ссылки в /usr/local/bin
- /Applications/Doxygen.app/Contents/MacOS/Doxywizard
, и всегда запуск мастера из терминала, какой вариант я выбрал.
Мой любимый и самый любимый состав - implicit_cast
. Это будет успешным только в том случае, если типы могут быть неявно преобразованы.
Полезно для преобразования из некоторого типа в void *
или из некоторого производного класса в базовый (если вы хотите выбрать конкретный экземпляр перегруженной функции или конструктора) или для безопасного добавления квалификаций const и любой другой сценарий, в котором вам действительно нужны неявные преобразования, и даже static_cast
слишком мощный.
Также прочтите Как C ++ выбирает, какую перегрузку вызывать .
template<typename T> struct identity { typedef T type; };
template<typename Dst> Dst implicit_cast(typename identity<Dst>::type t)
{ return t; }
There's also the function-style cast which looks like a function or constructor call. This resolves to the constructor call for classes, and (more generally) to C-style casts for all other types.
Examples:
int x = int(1.0); // equals `(int)1.0`
string s = string("x"); // equals call to constructor
The call to a constructor can also be achived using an explicit cast (apart from the C-style cast which would also work):
string s = static_cast<string>("x"); // is the same as above!
Стоит помнить, что конструкторы также могут действовать как приведения и будут использоваться компилятором для выполнения преобразований, подобных приведению. Например:
class Person {
public:
Person( const std::string & name );
...
};
Конструктор Person выполняет преобразование из строки -> Person:
Person p = Person( "fred" );
и будет использоваться компилятором, когда строку необходимо преобразовать в человека:
void PrintPerson( const Person & p ) {
...
}
теперь компилятор может преобразовать строку в Человек:
string name = "fred";
PrintPerson( name );
, но обратите внимание, что он не может этого сделать:
PrintPerson( "fred" );
, так как это потребует от компилятора построения цепочки преобразований.
Изменить: Я отправил дополнительный вопрос по теме преобразований - см. Неявные преобразования C ++ .
Возможно, вы захотите использовать приведение указателя ускорения (boost :: static_pointer_cast, ...), если вы используете shared_ptr. Их также можно использовать для стандартных указателей.
Одно действительно полезное приведение к ускорению - это оператор (действительно функция) numeric_cast (number);
Это проверяет, находится ли преобразовываемое число в диапазоне для типа назначения.
например,
long long big_number = ....
int num = numeric_cast<int>(big_number); // throws an exception is big_number is too big
Есть также ужасный union_cast .
Это плохо, потому что строго говоря, это UB, но если вы знаете, что делаете,
ACE имеет truncate_cast . В основном это полезно для оптимизации кода, подобного следующему:
foo_t bar = ...;
short baz;
if (bar > SHORT_MAX)
baz = SHORT_MAX;
else
baz = static_cast<short> (bar);
Его можно заменить на:
foo_t bar = ...;
short baz = ACE_Utils::truncate_cast<short> (bar);
В зависимости от базового типа foo_t , truncate_cast оптимизирует ] if () полностью, а также адрес диагностики компилятора в результате сравнения подписанных и беззнаковых типов. Выбор пути осуществляется во время компиляции с помощью метапрограммы шаблона.
В идеале такое приведение / усечение не требуется, если совместимые типы используются правильно, но иногда несовместимые типы невозможно обойти при работе с устаревшими интерфейсами. , особенно с низкоуровневыми вызовами ОС.
Обратите внимание, что таким приведением легко злоупотребить,
Visual Studio 6 разрешила rvalue связываться с обычными ссылками (не путать со ссылками на rvalue C ++ 0x ). При переносе на Visual Studio 2003 все места, в которых наш код зависел от этого нестандартного поведения, пришлось изменить.
Например, Определение
bool get_string(char* buff, int& length)
{
if (myStrLength >= length)
{
length = myStrLength;
return false; // Nobody used exceptions in 1998 :o)
}
strcpy(buff, myStr);
return true;
}
Использование:
char buff[1024];
get_string(buff, sizeof(buff)); // Assumes size is sufficient
Чтобы сделать порт намного быстрее, мы написали следующее lvalue_cast
.
// Danger, only use this on function arguments that will not be stored
template <class T>
T& lvalue_cast(const T& t)
{
return const_cast<T&>(t);
}
Поскольку временный объект находится в области видимости до следующей точки (следующей точки с запятой) и rvalue не соответствует действительности const
s, это четко определено (по крайней мере, в моем понимании).
Есть аналоги операторов приведения C ++, определенных в Boost.Lambda , которые очень полезны в различных лямбда-выражениях от простых:
vector<int> v1; // signed indices
v1.push_back(0);
v1.push_back(1);
v1.push_back(2);
vector<size_t> v2(v1.size()); // unsigned +1 incides
std::transform(v1.begin(), v1.end(), v2.begin(),
(boost::lambda::ll_static_cast<size_t>(boost::lambda::_1) + 1));
до гораздо более сложных с использованием оператора ll_dynamic_cast
, например, для фильтрации объектов определенного (производного) типа в последовательности :