ldd /usr/local/bin/<name>* | grep <something>
Instantiate template class or function in cpp
Class:
template class A< ConcreteType >;
Function:
template void A::function< ConcreteType >( int, float );
Note, add namespace if necessary.
Traits and Template Partial Specialisation – 2
template< class InputIterator, class Distance >
void advance( InputIterator &i, Distance n )
{
if( is_random_access_iterator( I ) ) {
advance_RAI( i, n );
} else if( is_bidirectional_iterator( I ) ) {
advance_BI( i, n );
} else {
advance_II( i, n );
}
}
The disadvantage of this approach is which advance_xx() is going to be used is determined during runtime, not at compile time, and thus the performance is not ideal.
Overloading mechanism can address this problem.
// Define five tag types
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};
These classes are only used as tags, and no need any members.
Now, the above advance_xx() functions can be written like below:
template< class InputIterator, class Distance >
inline void __advance( InputIterator &i, Distance n, input_iterator_tag )
{
while( n-- ) ++I;
}
template< class ForwardIterator, class Distance >
inline void __advance( ForwardIterator &i, Distance n, forward_iterator_tag )
{
advance( i, n, input_iterator_tag() );
}
template< class BidirectionalIterator, class Distance >
inline void __advance( BidirectionalIterator &i, Distance n, bidirectional_iterator_tag )
{
if( n >= 0 ) {
while( n-- ) ++i;
} else {
while( n++ ) --i;
}
}
template< class RandomAccessIterator, class Distance >
inline void __advance( RandomAccessIterator &i, Distance n, random_access_iterator_tag )
{
i += n;
}
The third parameter is only used to invoke overloading mechanism.
Now, the interface advance() is much simpler as below:
template< class InputIterator, class Distance >
void advance( InputIterator &i, Distance n )
{
__advance( i, n, iterator_traits< InputIterator >::iterator_category() );
}
In addition, to achieve the above feature, traits needs another type:
template< class I >
struct iterator_traits {
...
typedef typename I::iterator_category iterator_category;
};
// Partial specialisation for raw pointer
template< class T >
struct iterator_traits< T* > {
...
// Note, raw pointer is of RandomAccessIterator
typedef random_access_iterator_tag iterator_category;
};
// Partial specialisation for pointer-to-const
template< class T >
struct iterator_traits< const T* > {
...
// Similarly, pointer-to-const is also of RandomAccessIterator
typedef random_access_iterator_tag iterator_category;
};
Traits and Template Partial Specialisation – 1
In C++, template argument deduction doesn’t work for function return type. One solution is using nested type like below:
template< class T >
struct MyIter {
typedef T value_type; // nested type
T* ptr_;
MyIter( T* p=nullptr ) : ptr_( p ){}
T& operator*() const { return *ptr_; }
};
template< class I >
typename I::value_type func( I iter )
{
return *iter;
}
// ...
MyIter< int > iter( new int(8) );
cout << func( iter ); // Output: 8
A drawback of this approach is not all iters are of class type, e.g. raw pointer. It’s not possible to define nested type for a raw pointer.
Traits and Template partial specialisation can address this.
// Traits
template< class I >
struct iterator_traits
{
typedef typename I::value_type value_type;
}
// Template Partial Specialisation for T*
template< class T >
typename iterator_traits< T* >
{
typedef T value_type;
}
// Template Partial Specialisation for const T*
template< class T >
typename iterator_traits< const T* >
{
typedef T value_type; // Note, here should be T rather than const T
}
The above func() could be written like below:
template< class I >
typename iterator_traits< I >::value_type func( I iter )
{
return *iter;
}
Assert exception during python unit test
If using unittest:
import unittest
with self.assertRaises( Exception ) as error:
...
If using pytest:
import pytest
with pytest.raises( Exception ) as error:
...
Resize VirtualBox hard disk capacity
VBoxManage modifyhd <file_name>.vdi --resize 40960
Solution to “Another app is currently holding the yum lock; waiting for it to exit”
cat /var/run/yum.pid
<pid>
kill -9 <pid>
To get more details, use
ps -p <pid>
or
ps -ef | grep <pid>
Use gdb
gdb <binary>
gdb --args <binary> -i ...
(gdb) break filename:linenum
(gdb) step
(gdb) stepi
(gdb) next
(gdb) nexti
(gdb) finish
(gdb) continue
(gdb) until
(gdb) frame <frame #>
(gdb) info args
(gdb) info locals
(gdb) p <variable name>
(gdb) clear linenum
(gdb) clear filename:linenum
(gdb) info break
(gdb) del <breakpoint #>
(gdb) del <start #> - <end #>
(gdb) help <option name>
Redirect build outputs to a file
make &> build.txt
All build outputs including warnings and errors will be redirected to build.txt. If without &, errors and warnings will not be redirected to the file.
Avoid large ICONs and fonts for Qt5 applications in CentOS
export QA_AUTO_SCREEN_SCALE_FACTOR=0
export QT_SCALE_FACTOR=1
These two settings are BOTH required.