The ExTrait library is a library that focuses on metaprogramming and templates and types in general.
Since templates and general metaprogramming are sometimes awful to look at and hard to track why and how they do things the way they do, this library aims at abstracting many of these questions away, attempting to make them more reasonable and readable to the human eye. Hence a lot of the things that this library provides might look awful in the implementation, but provide a meaningful, concise and accessible interface.
The ExTrait library can do a lot and probably even more than that. If you ever wanted to deal with types in a class template parameter list, maybe add one? maybe filter some? maybe even SORT THEM? All of this is possible with the help of this library.
If you are asking yourself whether you need this and don't find an answer to that question, then this is the right library for you, because the weirdest cases sometimes require the weirdest solutions.
As an example, presume we have a std::tuple that has a type too much:
int main()
{
using MyTuple = std::tuple<double, int, long, float>;
// I don't need float in there
using MyFloatLessTuple = extrait::remove_t<MyTuple, float>;
std::cout << extrait::getActualTypeName<MyFloatLessTuple>() << '\n';
}
Now the tuple will NOT have the float
type any longer, nice, isn't it?
We can also get way more sophisticated here:
int main()
{
using MyTuple = std::tuple<double, int, long, float>;
// I don't want ANY floating point types here
using MyFloatingPointLessTuple = extrait::removeIf_t<MyTuple, std::is_floating_point>;
std::cout << extrait::getActualTypeName<MyFloatingPointLessTuple>() << '\n';
}
And WOOSH we only remain with a std::tuple<int, long>
, if that's not magic I don't know what is.
We can take it EVEN FURTHER!
template<class L, class R>
struct CharComparer
{
static constexpr bool value = (extrait::getActualTypeName<L>()[0] > extrait::getActualTypeName<R>()[0]);
};
int main()
{
using MyTuple = std::tuple<double, int, long, float, bool, char>;
using SortedTuple = extrait::sort_t<MyTuple, CharComparer>;
std::cout << extrait::getActualTypeName<SortedTuple>() << '\n';
}
Which will sort the types based on the size of the first char from the compile time name of every type. (do note though, that this example will heavily depend on the type output from the compiler, it might after all not be the same for every compiler, this example was tested only with GCC)
But this is not it, the library also provides serialisation for objects, function reflection, many many type traits and more.
This section deals with a quick start guide for installation using CMake, for a more detailed guide go here.
# Discover the library somewhere in your project hierarchy
add_subdirectory(path/to/extrait)
# Tell the linker to use this library
target_link_libraries(TargetName
PRIVATE
ExTrait)
Since this is a header-only library, you can just copy the includes/extrait
folder into your own header folder, but make sure to copy the extrait
folder and not only what is in there.
If you decided that you wanted to use this library for your project, there is a full documentation page over on our wiki page.
Here are a few useful links:
This library is separated into smaller components that may depend on each other. More information about what a component is here.
Name | Summary |
---|---|
Common | Provides a common tool set of template and type utilities. |
Type List | Provides a set of template utilities to deal with type-only parameter lists of class templates. |
Reflection | Provides a set of tools to deal with the inspection of types. |
Serialisation | Provides a toolset that allows dealing with types and strings. |
This Project started as part of another library, for a framework called the JUCE Framework, which is a framework for C++ that allows dealing with audio development in a simpler way than with other APIs.
However, these classes and interfaces had little to no dependency on the actual framework and hence it wouldn't have made much sense to leave it as that, as part of another framework. So the decision was made to cut ties with the framework in this instance and make it available to anyone that might benefit from it.
Back when this library was still part of the other library, a few things were needed for some of the other projects, a way to deal with lists of types to do things based on them. Which, majorly, were to tune down the usage of inheritance by simulating an interface with several classes and then, via std::variant, call the object's methods. Interestingly, this was the case more often than not, thus the interface called TypeArray was born.
The reason why it was called that is that there needed to be a way to simulate an std::array, but for types instead. For obvious reasons, this presented a challenge, you can't just deal with types the same way as with objects in an array, so the conclusion came after some time, trying to model the std array interface: "How about modelling it in a way that resembles C++'s type traits?" This is exactly what turned out to be the solution, this class was created and now included plenty of new type traits that would later become an interface that we now know as extrait::TypeArray.
Similarly, there were times when there was a need for stringifying types, majorly for logging purposes. There was a similar function in the standard, namely std::to_string, however, it does not provide an interface that would allow overriding the method for custom types except if you were to be using ADL.
But it was not desirable to use using std::to_string
for that, so it was about time to do something similar to what other libraries were already doing, which is some sort of adapter template that users can plug their custom types in with their own template specialisations and this was indeed a great solution. This is how "Stringable" came to be and later ported to this library as extrait::Stringable.
After the realisation that all of these things might come in handy outside of the framework that was being used, the consideration arrived: "Might not more people have a use for these things?". Said and done!
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
If you need more information or would like to contact us, you can find us on our Discord: