Releases: Manu343726/siplasplas
Bugfixes on the 0.0.2 version for Meeting C++
add_prebuild_command()
cmake command inutils.cmake
was invokingadd_dependencies()
even when the target has no dependencies.- Diego Rodriguez Losada Parser (
DRLParser
) was ignoring blacklist rules in nested paths DRLParser
is packaged with executable permissions enabled
Minor fixes. More examples for Meeting C++ 2016
- Minor doc fixes
- siplasplas-constexpr: constexpr algorithms and strings
- ctti dependency updated
- Typelist sorting
- Protobuf static-reflection example
- libclang setup fixes
- cpp::TypeInfo traits set fixes
- And more... (Look at the log, as I've done to write this changelog :P)
Meeting C++ 2016 feature complete!
This release finishes with the cleanup and refactoring work I have been doing to the API. Now the API has alll the features I want to show in the Meeting C++ 2016 talk
The current API docs can be seen here (There are also experimental Standardese docs here).
The release includes a packaged version of siplasplas, with all the cmake scripts to work (See installation in the readme) and siplasplas modules built as dynamic libraries using GCC 6.1.2 on Arch Linux.
packaging and static reflection test release
This is not a production ready release, but a packaged version of siplasplas to check the configuration and behavior of siplasplas when not being used from sources. The main purpose of this release is to check:
- Packaging layout: We test if the installation layout defined by the siplasplas configuration works as expected. We currently distribute the siplasplas headers in an
include/
dir, the prebuilt siplasplas modules in alib/
dir, and the reflection parser tools inbin/
. The package also contains a set of cmake scripts that may be used for easy configuration of siplasplas reflection,cmake/
dir. - cmake tools: We also test if the cmake tools menctioned above work as expected with the packaged distribution. The goal is to be able to use siplasplas reflection by just downloading the package and including the
cmake/siplasplas.cmake
script. Also, the siplasplas project includes abootstrap.cmake
script that can be used to automatically download and configure siplasplas by just including that file in your project. - static reflection on real world projects
This packaged version of siplasplas supports:
- static reflection: The siplasplas-reflection-static module and its dependencies are header only and C++11 compatible. Also, the code generated by the reflection tool (DRLParser) is header only and C++11 compatible too.
This release doesn't provide:
- Required includes of 3rdParty siplasplas dependencies: This means that any siplasplas module depending on an external dependency (Such as ctti, spdlog, or fmt) will not work in this release.
- Reflection metadata headers: Some siplasplas modules use static reflection and rely on the metadata generated by siplasplas (Mainly siplasplas-fswatch and siplasplas-cmake). That headers are not included in this release.
Playing with this release
Download bootstrap.cmake
file from the master branch and include it in your project CMakeLists.txt
as follows:
# URL to the release package:
set(SIPLASPLAS_PACKAGE_URL "https://github.com/Manu343726/siplasplas/releases/download/0.0.0/siplasplas-master-Clang-3_8_1-Debug-dynamic.tar.gz")
# Libclang version used by siplasplas reflection parser:
set(SIPLASPLAS_LIBCLANG_VERSION 3.8.1)
# Download libclang automatically (Easier than setting up libclang in your system):
set(SIPLASPLAS_DOWNLOAD_LIBCLANG ON)
# Install reflection parser Python dependencies automatically (Requires [pip](https://pip.pypa.io/en/stable/) for python 2.7)
set(SIPLASPLAS_INSTALL_DRLPARSER_DEPENDENCIES ON)
include(bootstrap.cmake)
To enable static reflection, invoke configure_siplasplas_reflection()
cmake command with your target as parameter:
add_library(MyLib mylib.cpp)
target_include_directories(MyLib PUBLIC ${CMAKE_SOURCE_DIR}/include)
target_compile_options(MyLib PRIVATE -std=c++11)
configure_siplasplas_reflection(MyLib)
This will install a pre-build target to run DRLParser before building your library.
To make static reflection available for a header, include <reflection/[full path to the header]>
at the end of the header file:
// myProjectSourceDir/include/mylib.h
#ifndef MYLIB_H
#define MYLIB_H
namespace MyLib
{
class MyClass
{
public:
enum class Enum
{
FOO,
BAR,
QUUX
};
int doSomething(const std::string& param);
int i = 0;
};
}
#include <reflection/mylib.h>
#endif // MYLIB_H
Here's a link to the latest master
documentation of siplasplas: https://manu343726.github.io/siplasplas/doc/doxygen/master/modules.html (Standardese version here).
Please note the library is still on development and the documentation is incomplete. Feel free to open an issue reporting any problem you have with the docs.
Static reflection API
siplasplas currently lacks proper documentation of its reflection API, but heres a brief example of how the static reflection API works:
#include "mylib.h"
#include <siplasplas/utility/fusion.hpp>
#include <siplasplas/utility/meta.hpp>
#include <siplasplas/utility/function_traits.hpp>
#include <iostream>
int main()
{
MyLib::MyClass myObject;
// Get reflection info about MyLib::MyClass class:
using MyClassInfo = cpp::static_reflection::Class<MyLib::MyClass>;
// cpp::static_reflection::Class exposes public aliases with typelists to the members of a class, currently:
// - Classes: Public member classes
// - Methods: Public non-static member functions
// - Fields: Public non-static member objects
// - Enums: Public enums (C enum or C++11 enum class)
//
// siplasplas provides a simple C++11 compatible metaprogramming lib in <siplasplas/utility/meta.hpp>
// with common metafunctions to manipulate typelists (get, append, split, cat, fold, fmap...) and other tmp
// utilities (void_t, logarithmic index_sequence, simple arithmetic, etc)
//
// The utility module also provides a fusion.hpp library with C++14 tools to do heterogeneous operations on
// parameter packs, type packs, etc; similar to boost::fusion
//
// Class<>::Methods returns a cpp::meta::list<> typelist with cpp::static_reflection::Function<> instances with the
// information of all the public methods of the class:
// - Function::get(): Returns a member function pointer to the function
// - Function::type: Returns the type of the member function, e.g. void(Class::*)(). This type can be queried with
// cpp::function_signature<>, cpp::function_args<>, cpp::function_arguments<> etc (In header siplasplas/utility/function_traits.hpp) to get the signature of the function.
// - Function::SourceInfo: Returns the instance of cpp::static_reflection::SourceInfo with the source information
// of the function declaration:
// Function::SourceInfo::spelling(): Returns the name of the member function, e.g. "doSomething"
// Function::SourceInfo::displayName(): Returns the display name (function name with signature)
// of the function, e-g. "void doSomething(const std::string& param)"
// Function::SourceInfo::fullName(): Returns the full qualified name of the member function, e.g. "MyLib::MyClass::doSomething"
// - class_type: Type of the class the member function belongs to, e.g. MyLib::MyClass
//
using Methods = MyClassInfo::Methods;
// Print information of all methods of the class:
cpp::foreach_type<Methods>([&](auto type)
{
// This is just a cool way to say "Give me the actual type", don't worry about this
// tmp stuff
using Method = cpp::meta::type_t<decltype(type)>;
std::cout << "Method: " << Method::spelling() << std::endl;
std::cout << " Number of arguments: " << cpp::function_arguments<typename Method::type>::size << std::endl;
std::cout << " Const member function: " << std::boolalpha << cpp::function_kind<typename Method::type>() == cpp::FunctionSignature::CONST_MEMBER_FUNCTION << std::endl;
});
// cpp::static_reflection::Enum<> is the Class<> counterpart for enum types. It provides
// methods for de/serialization of enum values to/from strings (Constexpr in C++14 only),
// The set of enum values, the number of enum values, etc:
constexpr auto enumValue = cpp::static_reflection::Enum<MyLib::MyClass::Enum>::fromString("FOO");
static_assert(enumValue == MyLib::MyClass::Enum::FOO, "???");
}