Generic helper function which takes any enum value and returns that value cast to its integral representation.
template<typename E>
constexpr auto to_integral(E e) -> typename std::underlying_type<E>::type
{
return static_cast<typename std::underlying_type<E>::type>(e);
}
Since it is constexpr it can be used as follows:
std::array<int, to_integral(my_fields::field)> b;
http://stackoverflow.com/questions/14589417/can-an-enum-class-be-converted-to-the-underlying-type
This blog serves as a dumping ground for my own interests. On it you will find anything which I want to keep track of; links, articles, tips and tricks. Mostly it focuses on C++, Javascript and HTML, linux and performance.
Showing posts with label cpp. Show all posts
Showing posts with label cpp. Show all posts
Thursday, 14 May 2015
Tuesday, 10 March 2015
C++11 - Unevaluated operands
Operands of sizeof, typeid, decltype and noexcept are never evaluated
We therefore only need a declaration, not the definition, to use a function or object's name in these contexts
std::declval<T>() returns T&&
std::declval<T&>() returns T&
decltype( foo(std::declval<T>()) ) returns foo's return type when foo is called with T&&
declval allows us to provide a declaration without having to evaluate the expression (ie: in an unevaluated context) - useful for SFINAE etc
Example: testing for copy-assignability
template<class T>
class is_copy_assignable
{
template<class U, class=decltype(declval<U&>()=declval<const U&>())>
static true_type try_assignment(U&&);
template<class U>
static false_type try_assignment(...); // catch-all fallback
public:
using type = decltype(try_assignment(declval<T>()));
};
How this works:
try_assignment(...) will match anything, but is also always the worst match, so if the other try_assignment can match, it will.
type will be the return type of try_assignment, which will either be true_type or false_type
the true_type overload will only work if the expression U& = const U& is valid - ie: if it is copy assignable
We use a second template parameter to allow SFINAE to kick in. It is unnamed because we only use it for SFINAE.
Example: testing for copy-assignability, and requiring an lvalue reference return type
The above example doesn't force a requirement on the copy assignment returning an lvalue reference.
If we assign an alias template to the returned type:
template<class T>
using copy_assignment_t = decltype(declval<T&>() = declval<const T&>());
We can then check whether that is a T& in a SFINAE specialisation
template<class T, class=void>
struct is_copy_assignable
: std::false_type {};
template<class T>
struct is_copy_assignable<T, void_t<copy_assignment_t<T>>>
: std::is_same<copy_assignment_t<T>,T&> {};
We therefore only need a declaration, not the definition, to use a function or object's name in these contexts
std::declval<T>() returns T&&
std::declval<T&>() returns T&
decltype( foo(std::declval<T>()) ) returns foo's return type when foo is called with T&&
declval allows us to provide a declaration without having to evaluate the expression (ie: in an unevaluated context) - useful for SFINAE etc
Example: testing for copy-assignability
template<class T>
class is_copy_assignable
{
template<class U, class=decltype(declval<U&>()=declval<const U&>())>
static true_type try_assignment(U&&);
template<class U>
static false_type try_assignment(...); // catch-all fallback
public:
using type = decltype(try_assignment(declval<T>()));
};
How this works:
try_assignment(...) will match anything, but is also always the worst match, so if the other try_assignment can match, it will.
type will be the return type of try_assignment, which will either be true_type or false_type
the true_type overload will only work if the expression U& = const U& is valid - ie: if it is copy assignable
We use a second template parameter to allow SFINAE to kick in. It is unnamed because we only use it for SFINAE.
Example: testing for copy-assignability, and requiring an lvalue reference return type
The above example doesn't force a requirement on the copy assignment returning an lvalue reference.
If we assign an alias template to the returned type:
template<class T>
using copy_assignment_t = decltype(declval<T&>() = declval<const T&>());
We can then check whether that is a T& in a SFINAE specialisation
struct is_copy_assignable
: std::false_type {};
template<class T>
struct is_copy_assignable<T, void_t<copy_assignment_t<T>>>
: std::is_same<copy_assignment_t<T>,T&> {};
Thursday, 23 October 2014
C++ Correct multi threaded singleton initialisation
Correct double-checked locking pattern
1. Pointer must be atomic
2. Check, lock, check, construct
std::atomic<Foo*> foo { nullptr };
Foo* instance()
{
Foo* f = foo; // single load of foo
if (!f)
{
std::lock_guard<std::mutex> l(foo_lock);
if (!foo)
{
foo = f = new Foo(); // assign both foo and f
}
}
return f;
}
Even better, use std::unique_ptr and std::once to get automatic cleanup and less scaffolding
class Foo
1. Pointer must be atomic
2. Check, lock, check, construct
std::atomic<Foo*> foo { nullptr };
Foo* instance()
{
Foo* f = foo; // single load of foo
if (!f)
{
std::lock_guard<std::mutex> l(foo_lock);
if (!foo)
{
foo = f = new Foo(); // assign both foo and f
}
}
return f;
}
Even better, use std::unique_ptr and std::once to get automatic cleanup and less scaffolding
class Foo
{
public:
static Foo& instance()
{
std::call_once(_create, [=]{
_instance = std::make_unique<Foo>();
});
return *_instance;
}
private:
static std::unique_ptr<Foo> _instance;
static std::once_flag _create;
};
Or just use a function local static
Foo& Foo::instance()
{
static Foo foo;
return foo;
}
C++ decltype and auto type deduction
auto type deduction strips const, volatile and ref
const int& bar = foo;
auto baz = bar; // strips const and ref - therefore type of baz is int
decltype type deduction doesn't strip const, volatile and ref
const int& bar = foo;
decltype(bar) // does not strip const and ref - therefore type is const int&
const int& bar = foo;
auto baz = bar; // strips const and ref - therefore type of baz is int
decltype type deduction doesn't strip const, volatile and ref
// decltype of a name
const int& bar = foo;
decltype(bar) // does not strip const and ref - therefore type is const int&
// decltype of an expression
decltype(lvalue expression) always returns an lvalue reference
int arr[5];
arr[0] = 5;
decltype(arr[0]) // lvalue reference, therefore type is int&
C++ type information at run time
std::type_info::name and typeid(T).name() will give incorrect results, as required by the standard
use Boost.TypeIndex
#include <boost/type_index.hpp>
boost::type_index::type_id_with_cvr<T>().pretty_name();
boost::type_index::type_id_with_cvr<decltype(t)>().pretty_name();
use Boost.TypeIndex
#include <boost/type_index.hpp>
boost::type_index::type_id_with_cvr<T>().pretty_name();
boost::type_index::type_id_with_cvr<decltype(t)>().pretty_name();
C++14 mutable lambda and by-value and by-value init capture
by-value capture vs by-value init capture
by-value capture: type of `i` is `const int`
{
const int i = 0;
auto lambda = [i]() { };
}
by-value init capture: type of `i` is `int`
{
const int i = 0;
auto lambda = [i=i]() { };
}
lambda function call operator is const
error: by-value capture: type of `i` is `int`, but default lambda operator() is const member function
{
int i = 0;
auto lambda = [i]() { i = 1; };
}
error: by-value init capture: type of `i` is `int`, but default lambda operator() is const member function
{
const int i = 0;
auto lambda = [i=i]() { i = 1; };
}
making lambda function call operator mutable
error: by-value capture: type of `i` is `const int`, can't assign, even though lambda operator() is mutable member function
{
const int i = 0;
auto lambda = [i]() mutable { i = 1; };
}
by-value capture: type of `i` is `int`, and lambda operator() is mutable member function
{
int i = 0;
auto lambda = [i]() mutable { i = 1; };
}
by-value init capture: type of `i` is `int`, and lambda operator() is mutable member function
{
const int i = 0;
auto lambda = [i=i]() mutable { i = 1; };
}
by-value capture: type of `i` is `const int`
{
const int i = 0;
auto lambda = [i]() { };
}
by-value init capture: type of `i` is `int`
{
const int i = 0;
auto lambda = [i=i]() { };
}
lambda function call operator is const
error: by-value capture: type of `i` is `int`, but default lambda operator() is const member function
{
int i = 0;
auto lambda = [i]() { i = 1; };
}
error: by-value init capture: type of `i` is `int`, but default lambda operator() is const member function
{
const int i = 0;
auto lambda = [i=i]() { i = 1; };
}
making lambda function call operator mutable
error: by-value capture: type of `i` is `const int`, can't assign, even though lambda operator() is mutable member function
{
const int i = 0;
auto lambda = [i]() mutable { i = 1; };
}
by-value capture: type of `i` is `int`, and lambda operator() is mutable member function
{
int i = 0;
auto lambda = [i]() mutable { i = 1; };
}
by-value init capture: type of `i` is `int`, and lambda operator() is mutable member function
{
const int i = 0;
auto lambda = [i=i]() mutable { i = 1; };
}
Sunday, 29 June 2014
bjam / boost.build
Boost.Build
Common signature:
rule rule-name
(
target-name :
sources + :
requirements * :
default-build * :
usage-requirements *
)
target-name is the name used to request the target
sources is the list of source files or other targets
requirements is the list of properties that must always be present when building this target
default-build is the list of properties that will be used unless some other value is already specified (eg: on cmd line or propagation from a dependent target)
usage-requirements is the properties that will be propagated to all targets that use this one
Helper commands:
glob - takes a list shell pattern and returns the list of files in the project's source directory that match the pattern. optional second argument is a list of exclude patterns
lib tools : [ glob *.cpp : exclude.cpp ] ;
glob-tree - recursive glob
lib tools : [ glob-tree *.cpp : .svn ] ;
constant - project wide constant
constant VERSION : 1.34.0 ;
Project:
project project-name
: requirements <feature>value <feature>value
;
Programs:
exe app-name
: app.cpp some_library.lib ../project//library
: <threading>multi
;
sources is one cpp file (app.cpp), a library in the same directory (some_library.lib) and a Jamfile target (library) specified in the Jamfile found in the path ../project
requirements is that threading is multi
Libraries:
Library targets can represent:
Libraries that should be built from source
Common signature:
rule rule-name
(
target-name :
sources + :
requirements * :
default-build * :
usage-requirements *
)
target-name is the name used to request the target
sources is the list of source files or other targets
requirements is the list of properties that must always be present when building this target
default-build is the list of properties that will be used unless some other value is already specified (eg: on cmd line or propagation from a dependent target)
usage-requirements is the properties that will be propagated to all targets that use this one
Helper commands:
glob - takes a list shell pattern and returns the list of files in the project's source directory that match the pattern. optional second argument is a list of exclude patterns
lib tools : [ glob *.cpp : exclude.cpp ] ;
glob-tree - recursive glob
lib tools : [ glob-tree *.cpp : .svn ] ;
constant - project wide constant
constant VERSION : 1.34.0 ;
Project:
project project-name
: requirements <feature>value <feature>value
;
Programs:
exe app-name
: app.cpp some_library.lib ../project//library
: <threading>multi
;
sources is one cpp file (app.cpp), a library in the same directory (some_library.lib) and a Jamfile target (library) specified in the Jamfile found in the path ../project
requirements is that threading is multi
Libraries:
Library targets can represent:
Libraries that should be built from source
lib lib-name
: lib.cpp
;
sources is one cpp file (lib.cpp)
Prebuilt libraries which already exist on the system
Such libraries can be searched for by the tools using them (typically with the linker's -l option), or their paths can be known in advance by the build system.
: lib.cpp
;
sources is one cpp file (lib.cpp)
Prebuilt libraries which already exist on the system
Such libraries can be searched for by the tools using them (typically with the linker's -l option), or their paths can be known in advance by the build system.
lib z
:
: <name>z <search>../3rd/libz
;
:
: <name>z <search>../3rd/libz
;
lib compress
:
: <file>/opt/libs/libcompress.a
;
:
: <file>/opt/libs/libcompress.a
;
<name> specifies the name of the library without the standard prefixes and suffixes.
In the above example, z could refer to z.so, libz.a, z.lib etc
<search> specifies paths in which to search for the library (in addition to the default compiler paths)
<search> can be specified multiple times, or omitted (meaning only the default compiler paths will be searched)
Note that <search> paths are added to the linker search path (-L) for all libraries being linked in the target, which can potentially lead to libraries from another path being picked up first
Convenience helper syntax for prebuilt libraries
lib z ;
lib gui db aux ;
is the same as
lib z : : <name>z ;
lib gui : : <name>gui ;
lib db : : <name>db ;
lib aux : : <name>aux ;
Prebuilt libraries for different build variants
lib foo
:
: <file>libfoo_release.a <variant>release
;
lib foo
:
: <file>libfoo_debug.a <variant>debug
;
Referencing other libraries
When a library references another library, that library should be listed in its list of sources.
Specify library dependencies even for searched and prebuilt libraries
lib z ;
lib png : z : <name>png ;
How Boost.Build includes library dependencies
When a library has a shared library as a source, or a static library has another static library as a source, then an target linking to the first library will also automatically link to the source library
However, when a shared library has a static library as a source, then the shared library will be built such that it completely includes the static library (--whole-archive)
If you don't want this behaviour, you need to use the following:
lib a : a.cpp : <use>b : : <library>b ;
This says that library uses library b, and causes executables that link to a to also link to b, instead of a referring to b
Automatically add a library's header location to any upstream target's include path
When a library's interface is in a header file, you can set usage-requirements for the library to include the path where the header file is, so that any target using the library target will automatically get the path to its header added to its include search path
lib foo : foo.cpp : : : <include>. ;
Control library linking order
If library a "uses" library b, then library a will appear before library b.
Library a is considered to use library b is b is present either in library a's sources or its usage is listed in its requirements
The <use> feature can also be used to explicitly express a relationship.
lib z ;
lib png : : <use>z ;
exe viewer : viewer png z ;
z will be linked before png
Special helper for zlib.
zlib can be configured either to use precompiled binaries or to build the library from source.
Find zlib in the default system location
using zlib ;
Build zlib from source
using zlib : 1.2.7 : <source>/home/steven/zlib-1.2.7 ;
Find zlib in /usr/local
using zlib : 1.2.7 : <include>/usr/local/include <search>/usr/local/lib ;
Build zlib from source for msvc and find prebuilt binaries for gcc.
using zlib : 1.2.7 : <source>C:/Devel/src/zlib-1.2.7 : <toolset>msvc ;
using zlib : 1.2.7 : : <toolset>gcc ;
Builtin features:
variant - build variant. Default configuration values: debug, release, profile.
link - library linking. values: shared, static
runtime-link - binary linking. values: shared, static
threading - link additional threading libraries. values: single, multi
source - useful for adding the same source to all targets in the project (put <source> in requirements), or to conditionally include a source
library - useful for linking to the same libraries for all targets in the project
dependency - introduces a dependency on the target named by the value. If the declared target is built, the dependent target will be too
implicit-dependency - indicates the target named by the value may produce files which the declared target uses.
use - introduces a dependency on the target named by the value, and adds its usage requirements to the build properties of the target being declared. The dependency is not used in any other way.
dll-path - add a shared library search path.
hardcode-dll-path - hardcode the dll-path entries. Values: true, false.
cflags, cxxflags, linkflags - passed on to the corresponding tools.
include - add an include search path.
define - define a preprocessor symbol. A value can be specified: <define>symbol=value
warnings - control the warning level of the compiler. Values: off, on, all.
warnings-as-errors - turn on to have builds fail when a warning is emitted.
build - skips building the target. Useful to conditionally set the value. Values: no.
tag - customize the name of generated files. Value: @rulename, where rulename is the name of a rule with the signature: rule tag ( name : type ? : property-set ). The rule will be called for each target with the default name of the target, the type of the target, and property set. Return an empty string to use the default target name, or a non empty string to be used for the name of the target. Useful for encoding library version nos etc.
debug-symbols - Include debug symbols in the object files etc. Values: on, off.
Objects:
Change behaviour for only a single object file
obj foo : foo.cpp : <optimizarion>off ;
exe bar : bar.cpp foo ;
foo will be built with the special flags, and then van be pulled into other targets
Alias:
Alternative name for a group of targets
alias core : foo bar baz ;
Using core in the source list of any other target or on the command line will translate to the aliased group of targets
Change build properties
alias my_bar : ../foo//bar : <link>static ;
my_bar now refers to the bar target in the foo Jamfile, but has the requirement that it be linked statically
Specify a header only library
alias hdr_only_lib : : : : <include>/path/to/headers ;
Using hdr_only_lib will just add an include path to any targets
Propagation of usage-requirements
When an alias has sources, the usage-requirements of those sources are propagated as well.
lib lib1 : lib1src.cpp : : : <include>/path/to/lib1.hpp ;
Installing:
Installing a built target to a relative path
install dist : foo bar ;
foo and bar will be moved to the dist folder, relative to the Jamfile's directory
Installing a built target to specific location
install dist : foo bar : <location>/install/path/location
foo and bar will be moved to /install/path/location
Installing a built target to a path based on a conditional expression
install dist
: foo bar
: <variant>release:<location>dist/release
<variant>debug:<location>dist/debug ;
foo and bar will be installed to relative path dist/<build-variant>
Installing a built target to a path based on an environment variable
(see accessing environment variables below)
install dist : foo bar : <location>$(DIST) ;
Automatically install all dependencies
install dist
: foo
: <install-dependencies>on
<install-type>EXE
<install-type>LIB
;
Preserve directory hierarchy
install headers
: a/b/c.h
: <location>/tmp
<install-source-root>a
;
Install into several directories
use an alias rule to install to several directories
alias install : install-bin install-lib ;
install install-bin : apps : <location>/usr/bin ;
install install-lib : libs : <location>/usr/lib ;
set the RPATH
install installed : application : <dll-path>/usr/lib/snake
<location>/usr/bin ;
will allow the application to find libraries placed in the /usr/lib/snake directory.
Testing:
unit-testing
behaves just like exe rule, but the test is automatically run after building
runs the test through the launcher, eg: valgrind build/path/foo_test
Environment variables:
local foo = [ SHELL "bar" ] ;
Executing external programs:
import os ;
local SOME_PATH = [ os.environ SOME_PATH ] ;
exe foo : foo.cpp : <include>$(SOME_PATH) ;
Conditional expressions:
syntax
property ( "," property ) * ":" property
multiple properties can be combined
will link hello statically only when compiling with gcc on NT
Command reference:
http://www.boost.org/doc/libs/1_55_0/doc/html/bbv2/reference.html
In the above example, z could refer to z.so, libz.a, z.lib etc
<search> specifies paths in which to search for the library (in addition to the default compiler paths)
<search> can be specified multiple times, or omitted (meaning only the default compiler paths will be searched)
Note that <search> paths are added to the linker search path (-L) for all libraries being linked in the target, which can potentially lead to libraries from another path being picked up first
Convenience helper syntax for prebuilt libraries
lib z ;
lib gui db aux ;
is the same as
lib z : : <name>z ;
lib gui : : <name>gui ;
lib db : : <name>db ;
lib aux : : <name>aux ;
Prebuilt libraries for different build variants
lib foo
:
: <file>libfoo_release.a <variant>release
;
lib foo
:
: <file>libfoo_debug.a <variant>debug
;
Referencing other libraries
When a library references another library, that library should be listed in its list of sources.
Specify library dependencies even for searched and prebuilt libraries
lib z ;
lib png : z : <name>png ;
How Boost.Build includes library dependencies
When a library has a shared library as a source, or a static library has another static library as a source, then an target linking to the first library will also automatically link to the source library
However, when a shared library has a static library as a source, then the shared library will be built such that it completely includes the static library (--whole-archive)
If you don't want this behaviour, you need to use the following:
lib a : a.cpp : <use>b : : <library>b ;
This says that library uses library b, and causes executables that link to a to also link to b, instead of a referring to b
Automatically add a library's header location to any upstream target's include path
When a library's interface is in a header file, you can set usage-requirements for the library to include the path where the header file is, so that any target using the library target will automatically get the path to its header added to its include search path
lib foo : foo.cpp : : : <include>. ;
Control library linking order
If library a "uses" library b, then library a will appear before library b.
Library a is considered to use library b is b is present either in library a's sources or its usage is listed in its requirements
The <use> feature can also be used to explicitly express a relationship.
lib z ;
lib png : : <use>z ;
exe viewer : viewer png z ;
z will be linked before png
Special helper for zlib.
zlib can be configured either to use precompiled binaries or to build the library from source.
Find zlib in the default system location
using zlib ;
Build zlib from source
using zlib : 1.2.7 : <source>/home/steven/zlib-1.2.7 ;
Find zlib in /usr/local
using zlib : 1.2.7 : <include>/usr/local/include <search>/usr/local/lib ;
Build zlib from source for msvc and find prebuilt binaries for gcc.
using zlib : 1.2.7 : <source>C:/Devel/src/zlib-1.2.7 : <toolset>msvc ;
using zlib : 1.2.7 : : <toolset>gcc ;
Builtin features:
variant - build variant. Default configuration values: debug, release, profile.
link - library linking. values: shared, static
runtime-link - binary linking. values: shared, static
threading - link additional threading libraries. values: single, multi
source - useful for adding the same source to all targets in the project (put <source> in requirements), or to conditionally include a source
library - useful for linking to the same libraries for all targets in the project
dependency - introduces a dependency on the target named by the value. If the declared target is built, the dependent target will be too
implicit-dependency - indicates the target named by the value may produce files which the declared target uses.
use - introduces a dependency on the target named by the value, and adds its usage requirements to the build properties of the target being declared. The dependency is not used in any other way.
dll-path - add a shared library search path.
hardcode-dll-path - hardcode the dll-path entries. Values: true, false.
cflags, cxxflags, linkflags - passed on to the corresponding tools.
include - add an include search path.
define - define a preprocessor symbol. A value can be specified: <define>symbol=value
warnings - control the warning level of the compiler. Values: off, on, all.
warnings-as-errors - turn on to have builds fail when a warning is emitted.
build - skips building the target. Useful to conditionally set the value. Values: no.
tag - customize the name of generated files. Value: @rulename, where rulename is the name of a rule with the signature: rule tag ( name : type ? : property-set ). The rule will be called for each target with the default name of the target, the type of the target, and property set. Return an empty string to use the default target name, or a non empty string to be used for the name of the target. Useful for encoding library version nos etc.
debug-symbols - Include debug symbols in the object files etc. Values: on, off.
Change behaviour for only a single object file
obj foo : foo.cpp : <optimizarion>off ;
exe bar : bar.cpp foo ;
foo will be built with the special flags, and then van be pulled into other targets
Alias:
Alternative name for a group of targets
alias core : foo bar baz ;
Using core in the source list of any other target or on the command line will translate to the aliased group of targets
Change build properties
alias my_bar : ../foo//bar : <link>static ;
my_bar now refers to the bar target in the foo Jamfile, but has the requirement that it be linked statically
Specify a header only library
alias hdr_only_lib : : : : <include>/path/to/headers ;
Using hdr_only_lib will just add an include path to any targets
Propagation of usage-requirements
When an alias has sources, the usage-requirements of those sources are propagated as well.
lib lib1 : lib1src.cpp : : : <include>/path/to/lib1.hpp ;
lib lib2 : lib2src.cpp : : : <include>/path/to/lib2.hpp ;
alias static_libs : lib1 lib2 : <link>static ;
exe main : main.cpp static_libs ;
Compile main with lib1 and lib2 as static libraries, and their paths are added to the include search path
Installing:
Installing a built target to a relative path
install dist : foo bar ;
foo and bar will be moved to the dist folder, relative to the Jamfile's directory
Installing a built target to specific location
foo and bar will be moved to /install/path/location
Installing a built target to a path based on a conditional expression
(see conditional expressions below)
: foo bar
: <variant>release:<location>dist/release
<variant>debug:<location>dist/debug ;
foo and bar will be installed to relative path dist/<build-variant>
Installing a built target to a path based on an environment variable
(see accessing environment variables below)
: foo
: <install-dependencies>on
<install-type>EXE
<install-type>LIB
;
will find all targets foo depends on, and install those which are either executables or libraries.
: a/b/c.h
: <location>/tmp
<install-source-root>a
;
/tmp/b/c.h will be installed
use an alias rule to install to several directories
install install-bin : apps : <location>/usr/bin ;
install install-lib : libs : <location>/usr/lib ;
set the RPATH
install installed : application : <dll-path>/usr/lib/snake
<location>/usr/bin ;
will allow the application to find libraries placed in the /usr/lib/snake directory.
Testing:
unit-testing
unit-test foo_test : test.cpp foo ;
behaves just like exe rule, but the test is automatically run after building
testing through another application
unit-test foo_test : test.cpp foo : <testing.launcher>valgrind ;
runs the test through the launcher, eg: valgrind build/path/foo_test
local foo = [ SHELL "bar" ] ;
Executing external programs:
import os ;
local SOME_PATH = [ os.environ SOME_PATH ] ;
exe foo : foo.cpp : <include>$(SOME_PATH) ;
Conditional expressions:
syntax
property ( "," property ) * ":" property
multiple properties can be combined
exe hello : hello.cpp : <os>NT,<toolset>gcc:<link>static ;
will link hello statically only when compiling with gcc on NT
Command reference:
http://www.boost.org/doc/libs/1_55_0/doc/html/bbv2/reference.html
Tuesday, 24 June 2014
Sublime Text for C++ development
Best of Sublime Text
http://scotch.io/bar-talk/best-of-sublime-text-3-features-plugins-and-settings
Project -> Save Project As...
bjam build system
{
"shell_cmd": "bjam",
"file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
"selector": "source.cpp"
}
http://scotch.io/bar-talk/best-of-sublime-text-3-features-plugins-and-settings
Project -> Save Project As...
bjam build system
{
"shell_cmd": "bjam",
"file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
"selector": "source.cpp"
}
Packages:
Sublime GDB
CTags
Sofa theme
Sidebar Enhancements
Bracket highlighter
SFTP
Git
Git Gutter
Advanced New File
Terminal
Markdown Editing
Sublime REPL
Labels:
c++,
cpp,
programming,
sysadmin
Thursday, 19 June 2014
Eclipse configuration
Install from eclipse site, not apt-get:
http://www.eclipse.org/downloads/
I decompressed it into /opt/eclipse, and installed a symlink in /usr/bin
$ sudo ln -s /opt/eclipse/eclipse /usr/bin
Increase heap memory available to eclipse (prevents crashing):
$ vim /opt/eclipse/eclipse.ini
-vmargs
-Dosgi.requiredJavaVersion=1.6
-XX:MaxPermSize=1G
-Xms1G
-Xmx2G
Add support for C++11 features for the code inspection
Window -> Preferences -> C/C++ -> Build -> Settings -> Discovery (tab) -> CDT GCC Built-in Compiler Settings. There is "Command to get compiler specs", add "-std=c++11" in there.
Syntax Highlighting theme:
Add the eclipse-color-theme repo to Eclipse marketplace
Help -> Install New Software -> Add -> Location: http://eclipse-color-theme.github.com/update
Select color theme:
Window -> Preferences -> General -> Appereance -> Color Theme : select Monkai or Obsidian or RecognEyes
Editor line highlight colors, etc:
Window -> Preferences -> General -> Editors -> Text Editors
Annotations:
Window -> Preferences -> General -> Editors -> Text Editors -> Annotations
C/C++ Indexer Markers -> Uncheck all
Change default Build Action:
Window -> Preferences -> General -> Keys
Filter on "Build"
Remove Ctrl-B from Build All, and add it to Build Project
C++ build console:
Window -> Preferences -> C++ -> Build -> Console
Increase the number of lines
Set colors
Source hover popup:
Window -> Preferences -> C++ -> Editor
Source Hover Background
Automatically close:
Window -> Preferences -> C++ -> Editor -> Typing
Uncheck all auto-close
Editor mark occurrences:
Window -> Preferences -> C++ -> Editor -> Mark Occurrences
Uncheck "Keep marks when the selection changes"
Now restart eclipse to make sure your settings are saved.
Change scalability settings
Window -> Preferences -> C++ -> Editor -> Scalability
Increase number of lines to something larger
Unused:
Color theme:
http://marketplace.eclipse.org/content/eclipse-moonrise-ui-theme
Window -> Preferences -> General -> Appearance : select Dark or MoonRise
Remote System Explorer:
Help -> Install New Software
Search for Remote, I
New connection -> SSH Only
Connect
Sftp files -> navigate to src directory -> Rt click -> Create Remote Project
Project indexer search paths
Project -> Properties -> C++ General -> Paths & Symbols
Includes
Library Paths
eg:
Includes:
${QTDIR}/include
${QTDIR}/include/QtCore
${QTDIR}/include/QtWidgets
${QTDIR}/include/QtGui
Library paths
${QTDIR}/include
${QTDIR}/include/QtCore
${QTDIR}/include/QtWidgets
${QTDIR}/include/QtGui
http://www.eclipse.org/downloads/
I decompressed it into /opt/eclipse, and installed a symlink in /usr/bin
$ sudo ln -s /opt/eclipse/eclipse /usr/bin
Increase heap memory available to eclipse (prevents crashing):
$ vim /opt/eclipse/eclipse.ini
-vmargs
-Dosgi.requiredJavaVersion=1.6
-XX:MaxPermSize=1G
-Xms1G
-Xmx2G
Add support for C++11 features for the code inspection
Window -> Preferences -> C/C++ -> Build -> Settings -> Discovery (tab) -> CDT GCC Built-in Compiler Settings. There is "Command to get compiler specs", add "-std=c++11" in there.
Syntax Highlighting theme:
Add the eclipse-color-theme repo to Eclipse marketplace
Help -> Install New Software -> Add -> Location: http://eclipse-color-theme.github.com/update
Select color theme:
Window -> Preferences -> General -> Appereance -> Color Theme : select Monkai or Obsidian or RecognEyes
Editor line highlight colors, etc:
Window -> Preferences -> General -> Editors -> Text Editors
Annotations:
Window -> Preferences -> General -> Editors -> Text Editors -> Annotations
C/C++ Indexer Markers -> Uncheck all
C/C++ Occurrences -> Uncheck Text as Squiggly Line
Codan Errors -> Uncheck all
Codan Warnings -> Uncheck all
Codan Warnings -> Uncheck all
Window -> Preferences -> General -> Keys
Filter on "Build"
Remove Ctrl-B from Build All, and add it to Build Project
Window -> Preferences -> C++ -> Build -> Console
Increase the number of lines
Set colors
Source hover popup:
Window -> Preferences -> C++ -> Editor
Source Hover Background
Automatically close:
Window -> Preferences -> C++ -> Editor -> Typing
Uncheck all auto-close
Editor mark occurrences:
Window -> Preferences -> C++ -> Editor -> Mark Occurrences
Uncheck "Keep marks when the selection changes"
Now restart eclipse to make sure your settings are saved.
Change scalability settings
Window -> Preferences -> C++ -> Editor -> Scalability
Increase number of lines to something larger
Unused:
Color theme:
http://marketplace.eclipse.org/content/eclipse-moonrise-ui-theme
Window -> Preferences -> General -> Appearance : select Dark or MoonRise
Remote System Explorer:
Help -> Install New Software
Search for Remote, I
New connection -> SSH Only
Connect
Sftp files -> navigate to src directory -> Rt click -> Create Remote Project
Project indexer search paths
Project -> Properties -> C++ General -> Paths & Symbols
Includes
Library Paths
eg:
Includes:
${QTDIR}/include
${QTDIR}/include/QtCore
${QTDIR}/include/QtWidgets
${QTDIR}/include/QtGui
${QTDIR}/include
${QTDIR}/include/QtCore
${QTDIR}/include/QtWidgets
${QTDIR}/include/QtGui
Thursday, 1 May 2014
Solving SFINAE issues when you have overlapping conditions
Sometimes we have function templates which we want to use SFINAE on, but some of them have overlapping conditions, creating ambiguity
template<unsigned N, enable_if_t<is_multiple_of<N, 3>>...>
void print_fizzbuzz(){ std::cout << "fizz\n"; }
template<unsigned N, enable_if_t<is_multiple_of<N, 5>>...>
void print_fizzbuzz(){ std::cout << "buzz\n"; }
template<unsigned N, enable_if_t<is_multiple_of<N, 15>>...> // this is ambiguous
void print_fizzbuzz(){ std::cout << "fizzbuzz\n"; }
By using derived-to-base conversions we can create a total ordering for selecting SFINAE overloads.
That is, we resolve ambiguity by using the following inheritance hierarchy:
template<unsigned I> struct choice : choice<I+1>{};
template<class C, class T = int>
using enable_if_t = typename std::enable_if<C::value, T>::type;
template<int N, int M>
struct is_multiple_of : std::integral_constant<bool, N % M == 0>{};
//-------------------------------
template<unsigned I> struct choice : choice<I+1>{};
template<> struct choice<10>{}; // suitably high terminating condition
struct otherwise{ otherwise(...){} };
struct select_overload : choice<0>{};
//-------------------------------
template<unsigned N, enable_if_t< is_multiple_of<N, 15> >...>
void print_fizzbuzz(choice<0>) { std::cout << "fizzbuzz\n"; }
template<unsigned N, enable_if_t< is_multiple_of<N, 3> >...>
void print_fizzbuzz(choice<1>) { std::cout << "fizz\n"; }
template<unsigned N, enable_if_t< is_multiple_of<N, 5> >...>
void print_fizzbuzz(choice<2>) { std::cout << "buzz\n"; }
template<unsigned N>
void print_fizzbuzz(otherwise){ std::cout << N << "\n"; }
template<unsigned N = 1>
void do_fizzbuzz()
{
print_fizzbuzz<N>(select_overload{});
do_fizzbuzz<N+1>();
}
template<>
void do_fizzbuzz<50>()
{
print_fizzbuzz<50>(select_overload{});
}
//-------------------------------
int main()
{
do_fizzbuzz();
}
template<unsigned N, enable_if_t<is_multiple_of<N, 3>>...>
void print_fizzbuzz(){ std::cout << "fizz\n"; }
template<unsigned N, enable_if_t<is_multiple_of<N, 5>>...>
void print_fizzbuzz(){ std::cout << "buzz\n"; }
template<unsigned N, enable_if_t<is_multiple_of<N, 15>>...> // this is ambiguous
void print_fizzbuzz(){ std::cout << "fizzbuzz\n"; }
By using derived-to-base conversions we can create a total ordering for selecting SFINAE overloads.
That is, we resolve ambiguity by using the following inheritance hierarchy:
template<unsigned I> struct choice : choice<I+1>{};
choice<0> has a higher ordering than choice<1>, and we can therefore use choice<0> as a function parameter to make is_multiple_of<N, 15> a better overload, thereby resolving the ambiguity.
The complete fizzbuzz example:
#include <type_traits>
#include <iostream>template<class C, class T = int>
using enable_if_t = typename std::enable_if<C::value, T>::type;
template<int N, int M>
struct is_multiple_of : std::integral_constant<bool, N % M == 0>{};
//-------------------------------
template<unsigned I> struct choice : choice<I+1>{};
template<> struct choice<10>{}; // suitably high terminating condition
struct otherwise{ otherwise(...){} };
struct select_overload : choice<0>{};
//-------------------------------
template<unsigned N, enable_if_t< is_multiple_of<N, 15> >...>
void print_fizzbuzz(choice<0>) { std::cout << "fizzbuzz\n"; }
template<unsigned N, enable_if_t< is_multiple_of<N, 3> >...>
void print_fizzbuzz(choice<1>) { std::cout << "fizz\n"; }
template<unsigned N, enable_if_t< is_multiple_of<N, 5> >...>
void print_fizzbuzz(choice<2>) { std::cout << "buzz\n"; }
template<unsigned N>
void print_fizzbuzz(otherwise){ std::cout << N << "\n"; }
template<unsigned N = 1>
void do_fizzbuzz()
{
print_fizzbuzz<N>(select_overload{});
do_fizzbuzz<N+1>();
}
template<>
void do_fizzbuzz<50>()
{
print_fizzbuzz<50>(select_overload{});
}
//-------------------------------
int main()
{
do_fizzbuzz();
}
This excellent technique by Xeo, as described here
Using function template default parameters to elegantly create SFINAE overloads
Having read Remastered enable_if, some implementation was left as an exercise for the reader.
The article explains how to make use of function template default parameters to elegantly create SFINAE overloads.
Below is my implementation.
#include <iostream>
#include <type_traits>
// true iff all conditions ::values are true
template <typename Head, typename... Tail>
struct all
{
static constexpr bool value = Head::value && all<Tail...>::value;
};
template <typename Head>
struct all<Head>
{
static constexpr bool value = Head::value;
};
//---------------------------------
// scoped enum to allow for differentiation between enable/disable
namespace detail { enum class enabler {}; }
template <typename... Condition>
using enable_if_t = typename std::enable_if<all<Condition...>::value, detail::enabler>::type;
template <typename... Condition>
using disable_if_t = typename std::enable_if<!all<Condition...>::value>::type;
//---------------------------------
// example function showing SFINAE overloads
template <typename T,
enable_if_t< std::is_arithmetic<T>
, std::is_integral<T>
>...>
T twice(T t)
{
return 2*t;
}
template <typename T,
disable_if_t< std::is_arithmetic<T>
, std::is_integral<T>
>...>
T twice(T t)
{
return t + t;
}
//---------------------------------
int main()
{
std::cout << twice(5) << std::endl;
std::cout << twice(std::string("Hello world")) << std::endl;
return 0;
}
Read more here
The article explains how to make use of function template default parameters to elegantly create SFINAE overloads.
Below is my implementation.
#include <iostream>
#include <type_traits>
// true iff all conditions ::values are true
template <typename Head, typename... Tail>
struct all
{
static constexpr bool value = Head::value && all<Tail...>::value;
};
template <typename Head>
struct all<Head>
{
static constexpr bool value = Head::value;
};
//---------------------------------
// scoped enum to allow for differentiation between enable/disable
namespace detail { enum class enabler {}; }
template <typename... Condition>
using enable_if_t = typename std::enable_if<all<Condition...>::value, detail::enabler>::type;
template <typename... Condition>
using disable_if_t = typename std::enable_if<!all<Condition...>::value>::type;
//---------------------------------
// example function showing SFINAE overloads
template <typename T,
enable_if_t< std::is_arithmetic<T>
, std::is_integral<T>
>...>
T twice(T t)
{
return 2*t;
}
template <typename T,
disable_if_t< std::is_arithmetic<T>
, std::is_integral<T>
>...>
T twice(T t)
{
return t + t;
}
//---------------------------------
int main()
{
std::cout << twice(5) << std::endl;
std::cout << twice(std::string("Hello world")) << std::endl;
return 0;
}
Read more here
Tuesday, 29 April 2014
Exiting recursive function templates without using helper class templates and partial specialisation
Contrived examples follow, but they serve to illustrate partial specialisation of class templates vs exiting recursive function templates using a branch.
The old way: use a helper class template, partially specialise it with the recursion exit case, and call a static function on this class template from a function template:
#include <iostream>
// helper class template
template<typename T, unsigned idx>
struct foo_impl
{
static void fn(T t)
{
std::cout << t << " " << idx << std::endl;
foo_impl<T, idx - 1>::fn(t); // recursively call fn
}
};
// partial specialisation of helper class template for exit case
template<typename T>
struct foo_impl<T, 0>
{
static void fn(T) {} // do nothing exit case
};
// function template which uses helper class templates
template<unsigned idx, typename T>
void foo(T t)
{
foo_impl<T, idx>::fn(t);
}
int main()
{
foo<5>("Hello world");
return 0;
}
The old way: use a helper class template, partially specialise it with the recursion exit case, and call a static function on this class template from a function template:
#include <iostream>
// helper class template
template<typename T, unsigned idx>
struct foo_impl
{
static void fn(T t)
{
std::cout << t << " " << idx << std::endl;
foo_impl<T, idx - 1>::fn(t); // recursively call fn
}
};
// partial specialisation of helper class template for exit case
template<typename T>
struct foo_impl<T, 0>
{
static void fn(T) {} // do nothing exit case
};
// function template which uses helper class templates
template<unsigned idx, typename T>
void foo(T t)
{
foo_impl<T, idx>::fn(t);
}
int main()
{
foo<5>("Hello world");
return 0;
}
The new way: have the special case branch in the function template itself, and recursively call the function template from itself.
To prevent the compiler from barfing when instantiating the recursive path, the trick is to recursively call the function template with the same parameters for the special case. Even though this code path will never actually execute, it is needed so the compiler can parse the template.
#include <iostream>
template<unsigned idx, typename T>
void foo(T t)
{
if (idx == 0) // special exit case
return;
std::cout << t << " " << idx << std::endl;
// recursively call the function
foo<idx - (idx ? 1 : 0)>(t); // note recursion returns itself in special exit case (code path will actually never be reached)
}
int main()
{
foo<5>("Hello world");
return 0;
}
template<unsigned idx, typename T>
void foo(T t)
{
if (idx == 0) // special exit case
return;
std::cout << t << " " << idx << std::endl;
// recursively call the function
foo<idx - (idx ? 1 : 0)>(t); // note recursion returns itself in special exit case (code path will actually never be reached)
}
int main()
{
foo<5>("Hello world");
return 0;
}
Wednesday, 23 October 2013
atomics & fences
Acquire
cannot move anything up beyond an acquire
Release
cannot move anything down beyond a release
Note
acquire/release cannot be reordered with respect to each other
What does this mean?
instructions can be reordered from before an acquire to after an acquire
instructions can be reordered from after a release to before a release
acquire cannot be reordered before or after a release
release cannot be reordered before or after an acquire
std::atomic
read = load_acquire --> read the value == acquire the value
write = store_release --> write the value == release the value
Sequential Consistency
Transitivity / Causality
Total Store Order
cannot move anything up beyond an acquire
Release
cannot move anything down beyond a release
Note
acquire/release cannot be reordered with respect to each other
What does this mean?
instructions can be reordered from before an acquire to after an acquire
instructions can be reordered from after a release to before a release
acquire cannot be reordered before or after a release
release cannot be reordered before or after an acquire
std::atomic
read = load_acquire --> read the value == acquire the value
write = store_release --> write the value == release the value
Sequential Consistency
Transitivity / Causality
Total Store Order
Sunday, 18 August 2013
Generalized function evaluation
#include <type_traits>
#include <utility>
// functions, functors, lambdas, etc.
template<
class F, class... Args,
class = typename std::enable_if<!std::is_member_function_pointer<F>::value>::type,
class = typename std::enable_if<!std::is_member_object_pointer<F>::value>::type
>
auto eval(F&& f, Args&&... args) -> decltype(f(std::forward<Args>(args)...))
{
return f(std::forward<Args>(args)...);
}
// const member function
template<class R, class C, class P, class... Args>
auto eval(R(C::*f)() const, P&& p, Args&&... args) -> R
{
return (*p.*f)(std::forward<Args>(args)...);
}
template<class R, class C, class... Args>
auto eval(R(C::*f)() const, C& c, Args&&... args) -> R
{
return (c.*f)(std::forward<Args>(args)...);
}
// non-const member function
template<class R, class C, class P, class... Args>
auto eval(R(C::*f)(), P&& p, Args&&... args) -> R
{
return (*p.*f)(std::forward<Args>(args)...);
}
// member object
template<class R, class C>
auto eval(R(C::*m), const C& c) -> const R&
{
return c.*m;
}
template<class R, class C>
auto eval(R(C::*m), C& c) -> R&
{
return c.*m;
}
Taken from here: http://functionalcpp.wordpress.com/2013/08/03/generalized-function-evaluation/
#include <utility>
// functions, functors, lambdas, etc.
template<
class F, class... Args,
class = typename std::enable_if<!std::is_member_function_pointer<F>::value>::type,
class = typename std::enable_if<!std::is_member_object_pointer<F>::value>::type
>
auto eval(F&& f, Args&&... args) -> decltype(f(std::forward<Args>(args)...))
{
return f(std::forward<Args>(args)...);
}
// const member function
template<class R, class C, class P, class... Args>
auto eval(R(C::*f)() const, P&& p, Args&&... args) -> R
{
return (*p.*f)(std::forward<Args>(args)...);
}
template<class R, class C, class... Args>
auto eval(R(C::*f)() const, C& c, Args&&... args) -> R
{
return (c.*f)(std::forward<Args>(args)...);
}
// non-const member function
template<class R, class C, class P, class... Args>
auto eval(R(C::*f)(), P&& p, Args&&... args) -> R
{
return (*p.*f)(std::forward<Args>(args)...);
}
// member object
template<class R, class C>
auto eval(R(C::*m), const C& c) -> const R&
{
return c.*m;
}
template<class R, class C>
auto eval(R(C::*m), C& c) -> R&
{
return c.*m;
}
Taken from here: http://functionalcpp.wordpress.com/2013/08/03/generalized-function-evaluation/
Tuesday, 5 March 2013
SFINAE decltype comma operator trick
Note the decltype statement below contains 2 elements: reserve and bool: decltype(t.reserve(0), bool())
This is a trick using SFINAE and the comma operator: SFINAE will cull the function if 'reserve' doesn't exist and the comma operator will mean the result type of the decltype statement will be a bool.
This means we can easily implement an 'enable_if'esque statement to check for the existence of a member function called 'reserve'
// Culled by SFINAE if reserve does not exist or is not accessible
template <typename T>
constexpr auto has_reserve_method(T& t) -> decltype(t.reserve(0), bool()) { return true; }
// Used as fallback when SFINAE culls the template method
constexpr bool has_reserve_method(...) { return false; }
template <typename T, bool b>
struct Reserver
{
static void apply(T& t, size_t n) { t.reserve(n); }
};
template <typename T>
struct Reserver <T, false>
{
static void apply(T& t, size_t n) {}
};
template <typename T>
bool reserve(T& t, size_t n)
{
Reserver<T, has_reserve_method(t)>::apply(t, n);
return has_reserve_method(t);
}
(Thanks to Matthieu M for his post on stackoverflow here)
--------------------------
Another implementation which has 2 SFINAE functions to access a member int, items_n or items_c, ultimately falling back to 0 if neither exist
// culled by SFINAE if items_n does not exist
template<typename T>
constexpr auto has_items_n(int) -> decltype(std::declval<T>().items_n, bool())
{
return true;
}
// catch-all fallback for items with no items_n
template<typename T> constexpr bool has_items_n(...)
{
return false;
}
//-----------------------------------------------------
template<typename T, bool>
struct GetItemsN
{
static int value(T& t)
{
return t.items_n;
}
};
template<typename T>
struct GetItemsN<T, false>
{
static int value(T&)
{
return 0;
}
};
//-----------------------------------------------------
// culled by SFINAE if items_c does not exist
template<typename T>
constexpr auto has_items_c(int) -> decltype(std::declval<T>().items_c, bool())
{
return true;
}
// catch-all fallback for items with no items_c
template<typename T> constexpr bool has_items_c(...)
{
return false;
}
//-----------------------------------------------------
template<typename T, bool>
struct GetItemsC
{
static int value(T& t)
{
return t.items_c;
}
};
template<typename T>
struct GetItemsC<T, false>
{
static int value(T&)
{
return 0;
}
};
//-----------------------------------------------------
template<typename T>
int get_items(T& t)
{
if (has_items_n<T>(0))
return GetItemsN<T, has_items_n<T>(0)>::value(t);
if (has_items_c<T>(0))
return GetItemsC<T, has_items_c<T>(0)>::value(t);
return 0;
}
//-----------------------------------------------------
When you have two candidates function templates, and want to use SFINAE to choose between them, sometimes you may have a parameter for which both overloads will work.
To prevent ambiguity you can favour one overload over the other.
By using implicit type casting we can make one overload a better match, therefore resolving the ambiguity.
#include <iostream>
template<class T>
auto serialize_imp(std::ostream& os, T const& obj, int)
-> decltype(os << obj, void())
{
os << obj;
}
template<class T>
auto serialize_imp(std::ostream& os, T const& obj, long)
-> decltype(obj.stream(os), void())
{
obj.stream(os);
}
template<class T>
auto serialize(std::ostream& os, T const& obj)
-> decltype(serialize_imp(os, obj, 0), void())
{
serialize_imp(os, obj, 0);
}
struct X
{
void stream(std::ostream&) const
{
std::cout << "\nX::stream()\n";
}
};
int main(){
serialize(std::cout, 5);
X x;
serialize(std::cout, x);
}
--------------------------
Another implementation which has 2 SFINAE functions to access a member int, items_n or items_c, ultimately falling back to 0 if neither exist
// culled by SFINAE if items_n does not exist
template<typename T>
constexpr auto has_items_n(int) -> decltype(std::declval<T>().items_n, bool())
{
return true;
}
// catch-all fallback for items with no items_n
template<typename T> constexpr bool has_items_n(...)
{
return false;
}
//-----------------------------------------------------
template<typename T, bool>
struct GetItemsN
{
static int value(T& t)
{
return t.items_n;
}
};
template<typename T>
struct GetItemsN<T, false>
{
static int value(T&)
{
return 0;
}
};
//-----------------------------------------------------
// culled by SFINAE if items_c does not exist
template<typename T>
constexpr auto has_items_c(int) -> decltype(std::declval<T>().items_c, bool())
{
return true;
}
// catch-all fallback for items with no items_c
template<typename T> constexpr bool has_items_c(...)
{
return false;
}
//-----------------------------------------------------
template<typename T, bool>
struct GetItemsC
{
static int value(T& t)
{
return t.items_c;
}
};
template<typename T>
struct GetItemsC<T, false>
{
static int value(T&)
{
return 0;
}
};
//-----------------------------------------------------
template<typename T>
int get_items(T& t)
{
if (has_items_n<T>(0))
return GetItemsN<T, has_items_n<T>(0)>::value(t);
if (has_items_c<T>(0))
return GetItemsC<T, has_items_c<T>(0)>::value(t);
return 0;
}
//-----------------------------------------------------
When you have two candidates function templates, and want to use SFINAE to choose between them, sometimes you may have a parameter for which both overloads will work.
To prevent ambiguity you can favour one overload over the other.
By using implicit type casting we can make one overload a better match, therefore resolving the ambiguity.
#include <iostream>
template<class T>
auto serialize_imp(std::ostream& os, T const& obj, int)
-> decltype(os << obj, void())
{
os << obj;
}
template<class T>
auto serialize_imp(std::ostream& os, T const& obj, long)
-> decltype(obj.stream(os), void())
{
obj.stream(os);
}
template<class T>
auto serialize(std::ostream& os, T const& obj)
-> decltype(serialize_imp(os, obj, 0), void())
{
serialize_imp(os, obj, 0);
}
struct X
{
void stream(std::ostream&) const
{
std::cout << "\nX::stream()\n";
}
};
int main(){
serialize(std::cout, 5);
X x;
serialize(std::cout, x);
}
Here the ostream operator overload will be chosen when an object with both operator<< and stream() because by passing in 0 for the 3rd parameter of serialize_imp, we choose the overload with the int parameter, as 0 is an int, whereas the long parameter would require an implicit cast.
(Thanks to Xeo for his post on stackoverflow here)
Monday, 4 March 2013
Boost Compute - GPGPU programming
Pre-release version of boost compute by Kyle Lutz
http://kylelutz.github.com/compute/index.html
https://github.com/kylelutz/compute
http://kylelutz.github.com/compute/index.html
https://github.com/kylelutz/compute
Sunday, 3 March 2013
C++ implementation of the Disruptor pattern
original: https://github.com/fsaintjacques/disruptor--
fork: https://github.com/jwakely/disruptor--
fork: https://github.com/jwakely/disruptor--
Thursday, 29 November 2012
Pattern recognition algorithms
Boost based Computer Vision and Pattern Recognition Library implements many useful algorithms such as Principal Component Analysis, Eigen solver, etc.
http://boostcvpr.sourceforge.net/
http://boostcvpr.sourceforge.net/
Sunday, 4 November 2012
gtest - google unit testing framework
Primer
http://code.google.com/p/googletest/wiki/Primer
Simple test case
#include <gtest/gtest.h>
TEST(TestSuite, TestCase1)
{
ASSERT_TRUE(expr);
}
TEST(TestSuite, TestCase2)
{
ASSERT_TRUE(expr);
}
Get the main function for free
Link gtest_main.cc and you get RUN_ALL_TESTS free
What to do if a test fails
Abort the test on expression failure:
ASSERT_TRUE(expr);
Continue the test on expression failure:
EXPECT_TRUE(expr);
Floating point comparison:
EXPECT_FLOAT_EQ(val1, val2);
Command line options
Repeat tests (useful for finding subtle race conditions)
--gtest_repeat=1000
Enter the debugger upon test failure
--gtest_break_on_failure
Generate an xml report "foobar.xml"
--gtest_output="xml:foobar"
Only run some tests
--gtest_filter=TestSuite* // runs all suites matching TestSuite*
http://code.google.com/p/googletest/wiki/Primer
Simple test case
#include <gtest/gtest.h>
TEST(TestSuite, TestCase1)
{
ASSERT_TRUE(expr);
}
TEST(TestSuite, TestCase2)
{
ASSERT_TRUE(expr);
}
Get the main function for free
Link gtest_main.cc and you get RUN_ALL_TESTS free
What to do if a test fails
Abort the test on expression failure:
ASSERT_TRUE(expr);
Continue the test on expression failure:
EXPECT_TRUE(expr);
Floating point comparison:
ASSERT_FLOAT_EQ(val1, val2);
ASSERT_DOUBLE_EQ(val1, val2);
ASSERT_NEAR(val1, val2, epsilon);
EXPECT_FLOAT_EQ(val1, val2);
EXPECT_DOUBLE_EQ(val1, val2);
EXPECT_NEAR(val1, val2, epsilon);
Repeat tests (useful for finding subtle race conditions)
--gtest_repeat=1000
Enter the debugger upon test failure
--gtest_break_on_failure
Generate an xml report "foobar.xml"
--gtest_output="xml:foobar"
Only run some tests
--gtest_filter=TestSuite* // runs all suites matching TestSuite*
--gtest_filter=TestSuite*-*.*2 // runs all suites matching TestSuite* except cases ending in '2'
--gtest_filter=Foo*:Bar* // separate different reg-ex's with ':'
Monday, 24 September 2012
Open BEAGLE - open source genetic programming framework
Open BEAGLE is a C++ Evolutionary Computation (EC) framework. It provides an high-level software environment to do any kind of EC, with support for tree-based genetic programming; bit string, integer-valued vector, and real-valued vector genetic algorithms; and evolution strategy
http://code.google.com/p/beagle/
http://code.google.com/p/beagle/
Subscribe to:
Posts (Atom)