siplasplas
A library for C++ reflection and introspection
Utility

Some random utilities needed by other siplasplas modules. More...

Modules

 Assert
 Assertion utilities.
 
 Dynamic-library
 Cross platform API to load symbols from shared librarties at runtime.
 
 Error-handling
 Error handling tools.
 
 Hash
 Hashing utilities based on std::hash.
 
 Memory-manip
 Tools related to raw memory manipulation.
 

Classes

class  cpp::Identity
 A functor class implementing the identity function. More...
 
class  cpp::UniversalReference< T, IsLvalueReference, IsConst >
 Implements a copyable wrapper of an universal reference. More...
 
class  cpp::UniversalReference< T, true, false >
 UniversalReference spacialization for non-const lvalues. More...
 
class  cpp::UniversalReference< T, false, false >
 UniversalReference spacialization for rvalues. More...
 

Macros

#define SIPLASPLAS_UTILITY_COMPILES(...)
 Checks if an expression is well formed. More...
 

Functions

template<typename Expr >
constexpr auto cpp::compiles (Expr &&expr)
 Checks if an expression is well formed. More...
 
template<typename T >
void cpp::destroy (T &object)
 Invokes the destructor of an object. More...
 
template<typename T >
void cpp::destroy (T *objectPtr)
 Invokes the destructor of an object. More...
 
template<typename T , typename... Args>
void cpp::construct (void *where, Args &&...args)
 constructs an object of type T on the specified address More...
 
template<typename T , typename... Args>
void cpp::construct (T *where, Args &&...args)
 constructs an object of type T on the specified address More...
 
template<typename Callable , typename... Args>
decltype(auto) cpp::invoke (Callable &&callable, Args &&...args)
 Invokes the Callable object with the given arguments. See std::invoke()
 
template<typename T >
std::string cpp::lexical_cast (const T &value)
 Returns an string representation of a value. More...
 
template<typename T >
cpp::lexical_cast (const std::string &value)
 Returns an string representation of a value. More...
 
template<bool Condition, typename ThenBody , typename... Args>
auto cpp::staticIf (const ThenBody &thenBody, Args &&...args)
 Implements an static conditional. More...
 
template<typename T >
auto cpp::universalReference (T &&value) -> UniversalReference< std::decay_t< T >, std::is_lvalue_reference< T >::value, std::is_const< std::remove_reference_t< T >>::value >
 Creates an universal reference to the given value. More...
 

Detailed Description

Some random utilities needed by other siplasplas modules.

The siplaspals-utility module implements various utilities used in the implementation of other siplasplas modules. These utilities are not grouped in any special way, but we encourage the policy of rising utilities into full-fledged modules if these became too complex.

Todo:

Move meta.hpp, function_traits.hpp, tuple.hpp, and fusion.hpp to a siplasplas-meta module.

Move error_logger.hpp and exception.hpp to a siplasplas-exception module?

Move cpp::Overload<> to function_traits.hpp

siplasplas-utility includes the following features:

Macro Definition Documentation

#define SIPLASPLAS_UTILITY_COMPILES (   ...)

Checks if an expression is well formed.

This macro hides the syntax complexity of cpp::compiles() and checks directly whatever expression is passed as argument to the macro:

1 auto result = SIPLASPLAS_UTILITY_COMPILES(
2  identity(std::declval<std::string>()).append("hello")
3 );
4 
5 static_assert(!result, "std::string has no append() method");

Note there's an implicit identity variable available to delay the evaluation of the expression.

Parameters
Expressionto check
Returns
An implementation defined type constexpr-convertible to bool. The returned value converts to true if the expression is well formed, converts to false otherwise.

Function Documentation

template<typename Expr >
constexpr auto cpp::compiles ( Expr &&  expr)

Checks if an expression is well formed.

This function takes an expression in the form of an SFINAE-friendly context and checks if the expression can be compiled. For example:

auto result = cpp::compiles([](auto identity) -> decltype(
identity(std::declval<std::string>()).append("hello")
) {});
static_assert(!result, "std::string has no append() method");

The cpp::compiles(<test>) expression itself is not constexpr, so two steps are needed to perform the constexpr test. cpp::compiles() returns an implementation defined type that is constexpr-convertible to bool, giving the result of the test.

Parameters
exprA callable template of signature decltype(<expression to check>)(Identity). The identity parameter is given to delay the evaluation of the expression, making it dependent of a template of the test. If the expression is directly evaluable, an ill-formed expression would make the program compilation to fail.
Returns
An implementation defined type constexpr-convertible to bool. The returned value converts to true if the expression is well formed, converts to false otherwise.
template<typename T , typename... Args>
void cpp::construct ( void *  where,
Args &&...  args 
)

constructs an object of type T on the specified address

This function performs an in-place construction of an object of type T in the given address. Arguments are passed as-is to the object constructor. The behavior is undefined if alignment(pointer) != alignof(T).

Parameters
whereLocation of the object
argsConstructor arguments
std::aligned_storage<std::string> storage;
cpp::construct<std::string>(&storage, "hello, world!");
template<typename T , typename... Args>
void cpp::construct ( T *  where,
Args &&...  args 
)

constructs an object of type T on the specified address

This function performs an in-place construction of an object of type T in the given address. Arguments are passed as-is to the object constructor. The behavior is undefined if alignment(pointer) != alignof(T).

Parameters
whereLocation of the object
argsConstructor arguments
std::aligned_storage<std::string> storage;
std::string* stringPtr = reinterpret_cast<std::string*>(&storage);
cpp::construct(stringPtr, "hello, world!");
template<typename T >
void cpp::destroy ( T &  object)

Invokes the destructor of an object.

Template Parameters
TMust be Destructible (See std::is_destructible)
template<typename T >
void cpp::destroy ( T *  objectPtr)

Invokes the destructor of an object.

Template Parameters
TMust be Destructible (See std::is_destructible)
template<typename T >
std::string cpp::lexical_cast ( const T &  value)

Returns an string representation of a value.

This function invokes operator<<(std::ostream&, const T&) to get an string representation of a given value.

It's a simplified version of the Boost.Lexical_Cast library.

Template Parameters
Tvalue type. Must have a valid operator<<(std::ostream&, T) overload.
Parameters
valueValue which is translated to a string.
Returns
A string representation of the given value.
Examples:
examples/reflection/static/serialization.cpp.
template<typename T >
T cpp::lexical_cast ( const std::string &  value)

Returns an string representation of a value.

This function invokes operator>>(std::istream&, T&) to assign a T value from an string representation of it.

It's a simplified version of the Boost.Lexical_Cast library.

Template Parameters
TRequired output value type. Must have a valid operator>>(std::istream&, T&) overload.
Parameters
valueString representation of the value.
Returns
A value of type T equivalent to the value string representation argument.
template<bool Condition, typename ThenBody , typename... Args>
auto cpp::staticIf ( const ThenBody &  thenBody,
Args &&...  args 
)

Implements an static conditional.

An static conditional allows to conditionally evaluate some code depending on the value of a compile time property. The body of the conditional is implemented by user provided functions.

template<typename T>
void f(T value)
{
cpp::staticIf<std::is_integral<T>::value>([&](auto identity)
{
std::cout << "the value is integral\n";
});
...
}

The body of the untaken conditional path shall not be evaluated by the compiler and can contain ill formed code. NOTE: This behavior relies on the two phase template processing scheme, so the statement above is only true for entities that will be evaluated in the instantiation phase only:

template<typename T>
void foo(T value)
{
int i = 0;
// The condition is false, so the code
// inside the if "should" not be evaluated:
cpp::staticIf<false>([&](auto identity)
{
// Ok: value depends on T template parameter.
value.TheMostBizarreMethodName();
// ERROR: 'int' type is not class/struct/union.
i.method();
// Ok: identity(i) depends on a template parameter.
identity(i).method();
});
}

As the example shows, the conditional body takes an identity parameter that can be used to force the evaluation of an expression at the second phase.

The static conditional expression also provides an else sentence in the form of an Else() method:

template<typename T>
void foo(T value)
{
int i = 0;
cpp::staticIf<false>([&](auto identity)
{
value.TheMostBizarreMethodName();
i.method();
identity(i).method();
}).Else([&](auto identity)
{
std::cout << i << std::endl;
});
}

cpp::staticIf() supports returning values from the conditional body too:

template<typename T>
T twice(const T& value)
{
return cpp::staticIf<std::is_class<T>::value>([&](auto)
{
return value.twice();
}).Else([&](auto)
{
return value * 2;
});
}

note this has some caveats:

  • Return types cannot be inferred: Due to technical reasons auto or any other kind of type inference cannot be used with the return value of a static conditional.
  • Return may not be optimal in some code paths: If the condition is true, the then path is picked. If the then body returns a value, such value is not returned directly (So elligible for RVO) but bypassed through the else internals. This means returning a value from a positive conditional may involve two move operations.
Template Parameters
ConditionValue of the condition. The value should be evaluable at compile time, else compilation fails.
ThenBodyFunction type with one template-dependent value parameter.
Parameters
thenBodyBody of the then path of the conditional. Evaluated only if the condition is true.
Returns
An unspecified type implementing the else part of the conditional.
template<typename T >
auto cpp::universalReference ( T &&  value) -> UniversalReference< std::decay_t<T>, std::is_lvalue_reference<T>::value, std::is_const<std::remove_reference_t<T>>::value >

Creates an universal reference to the given value.

This function checks the value category of the given value and instances the apropiate cpp::UniversalReference specialization. Note the returned type depends on the value category. For an alternative with common a type, see cpp::typeerasure::AnyArg

Returns
A UniversalReference specialization instance as follows:
  • UniversalReference<std::decay_t<T>, true, true> if value type is deduced to a const reference to an lvalue.
  • UniversalReference<std::decay_t<T>, true, false> if value type is deduced to a non const reference to an lvalue.
  • UniversalReference<std::decay_t<T>, false, false> if value type is deduced to an rvalue reference