Skip to content

Commit 40aa753

Browse files
committed
Add and test example to README.
1 parent 2c2b33e commit 40aa753

File tree

5 files changed

+203
-66
lines changed

5 files changed

+203
-66
lines changed

README.md

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,70 @@
11
# traits
2-
A small header only utility library extending C++ traits
2+
A small header only utility library adding traits for function types in C++.
3+
4+
# Usage
5+
Add the CMakeLists.txt to your project via `add_subdirectory` and then include the header in your source files:
6+
(Or add the header directly to your project.)
7+
8+
```cmake
9+
cmake_minimum_required(VERSION 3.16) # or higher
10+
11+
add_subdirectory(traits)
12+
```
13+
14+
Then in your source files, you can include the header like this:
15+
```cpp
16+
#include <traits/functions.hpp>
17+
```
18+
19+
# Examples
20+
```cpp
21+
#include <traits/functions.hpp>
22+
23+
// All of these can be inspected:
24+
auto lambda = [](int x) { return x * 2; };
25+
26+
struct FunctionObject {
27+
int operator()(double x) const {
28+
return static_cast<int>(x);
29+
}
30+
31+
std::string memberFunction(double x) const& {
32+
return std::to_string(x);
33+
}
34+
};
35+
36+
double freeFunction(double x) {
37+
return x * 2.0;
38+
}
39+
40+
int main() {
41+
using namespace Traits;
42+
43+
// Example of using FunctionTraits with a lambda
44+
auto lambda = [](std::string const& x, std::size_t y) noexcept { return x.size() + y; };
45+
using LambdaTraits = FunctionTraits<decltype(lambda)>;
46+
47+
static_assert(LambdaTraits::arity == 2, "Lambda should have arity 1");
48+
static_assert(std::is_same_v<LambdaTraits::ReturnType, std::size_t>, "Lambda should return int");
49+
static_assert(std::is_same_v<LambdaTraits::Argument<0>, std::string const&>, "Lambda should take int as argument");
50+
static_assert(std::is_same_v<LambdaTraits::Argument<1>, std::size_t>, "Lambda should take size_t as argument");
51+
static_assert(
52+
std::is_same_v<LambdaTraits::ArgumentDecayed<0>, std::string>, "Lambda should take size_t as argument");
53+
static_assert(std::is_same_v<LambdaTraits::ArgsTuple, std::tuple<std::string const&, std::size_t>>);
54+
static_assert(std::is_same_v<LambdaTraits::ArgsTupleDecayed, std::tuple<std::string, std::size_t>>);
55+
static_assert(LambdaTraits::qualifiers.isConst, "Lambda is not mutable");
56+
static_assert(!LambdaTraits::qualifiers.isVolatile, "Lambda is not volatile");
57+
static_assert(LambdaTraits::qualifiers.isNoexcept, "Lambda is noexcept");
58+
static_assert(!LambdaTraits::qualifiers.isReferenceQualified, "Lambda is not reference qualified");
59+
static_assert(!LambdaTraits::qualifiers.isRvalueReferenceQualified, "Lambda is not rvalue reference qualified");
60+
static_assert(
61+
std::is_same_v<LambdaTraits::StandardFunctionType, std::function<std::size_t(std::string const&, std::size_t)>>,
62+
"Standard function type should match");
63+
static_assert(
64+
std::is_same_v<LambdaTraits::StandardFunctionTypeDecayed, std::function<std::size_t(std::string, std::size_t)>>,
65+
"Standard function type decayed should match");
66+
67+
return 0;
68+
}
69+
```
70+

include/traits/functions.hpp

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@ namespace Traits
1313
{
1414
bool isConst = false;
1515
bool isVolatile = false;
16-
bool isRef = false;
17-
bool isRvalueRef = false;
16+
bool isReferenceQualified = false;
17+
bool isRvalueReferenceQualified = false;
1818
bool isNoexcept = false;
1919

2020
constexpr bool operator==(const FunctionQualifiers& other) const noexcept
2121
{
22-
return isConst == other.isConst && isVolatile == other.isVolatile && isRef == other.isRef &&
23-
isRvalueRef == other.isRvalueRef && isNoexcept == other.isNoexcept;
22+
return isConst == other.isConst && isVolatile == other.isVolatile &&
23+
isReferenceQualified == other.isReferenceQualified &&
24+
isRvalueReferenceQualified == other.isRvalueReferenceQualified && isNoexcept == other.isNoexcept;
2425
}
2526
};
2627

@@ -72,15 +73,6 @@ namespace Traits
7273

7374
/// The function type as a std::function with decayed argument types (removes references and qualifiers).
7475
using StandardFunctionTypeDecayed = std::function<ReturnT(std::decay_t<Args>...)>;
75-
76-
struct AsStdFunctionImpl
77-
{
78-
using type = std::function<ReturnT(Args...)>;
79-
using DecayedType = std::function<ReturnT(std::decay_t<Args>...)>;
80-
};
81-
82-
using AsStdFunction = typename AsStdFunctionImpl::type;
83-
using AsStdFunctionDecayed = typename AsStdFunctionImpl::DecayedType;
8476
};
8577

8678
/**
@@ -125,34 +117,46 @@ namespace Traits
125117
namespace Detail
126118
{
127119
constexpr FunctionQualifiers cvQualified{.isConst = true, .isVolatile = true};
128-
constexpr FunctionQualifiers constRef{.isConst = true, .isRef = true};
129-
constexpr FunctionQualifiers volatileRef{.isVolatile = true, .isRef = true};
130-
constexpr FunctionQualifiers cvRef{.isConst = true, .isVolatile = true, .isRef = true};
131-
constexpr FunctionQualifiers constRvalueRef{.isConst = true, .isRvalueRef = true};
132-
constexpr FunctionQualifiers volatileRvalueRef{.isVolatile = true, .isRvalueRef = true};
133-
constexpr FunctionQualifiers cvRvalueRef{.isConst = true, .isVolatile = true, .isRvalueRef = true};
120+
constexpr FunctionQualifiers constRef{.isConst = true, .isReferenceQualified = true};
121+
constexpr FunctionQualifiers volatileRef{.isVolatile = true, .isReferenceQualified = true};
122+
constexpr FunctionQualifiers cvRef{.isConst = true, .isVolatile = true, .isReferenceQualified = true};
123+
constexpr FunctionQualifiers constRvalueRef{.isConst = true, .isRvalueReferenceQualified = true};
124+
constexpr FunctionQualifiers volatileRvalueRef{.isVolatile = true, .isRvalueReferenceQualified = true};
125+
constexpr FunctionQualifiers cvRvalueRef{
126+
.isConst = true,
127+
.isVolatile = true,
128+
.isRvalueReferenceQualified = true};
134129

135130
constexpr FunctionQualifiers constNoexcept{.isConst = true, .isNoexcept = true};
136131
constexpr FunctionQualifiers volatileNoexcept{.isVolatile = true, .isNoexcept = true};
137132
constexpr FunctionQualifiers cvNoexcept{.isConst = true, .isVolatile = true, .isNoexcept = true};
138-
constexpr FunctionQualifiers refNoexcept{.isRef = true, .isNoexcept = true};
139-
constexpr FunctionQualifiers rvalueRefNoexcept{.isRvalueRef = true, .isNoexcept = true};
140-
constexpr FunctionQualifiers constRefNoexcept{.isConst = true, .isRef = true, .isNoexcept = true};
141-
constexpr FunctionQualifiers volatileRefNoexcept{.isVolatile = true, .isRef = true, .isNoexcept = true};
133+
constexpr FunctionQualifiers refNoexcept{.isReferenceQualified = true, .isNoexcept = true};
134+
constexpr FunctionQualifiers rvalueRefNoexcept{.isRvalueReferenceQualified = true, .isNoexcept = true};
135+
constexpr FunctionQualifiers constRefNoexcept{
136+
.isConst = true,
137+
.isReferenceQualified = true,
138+
.isNoexcept = true};
139+
constexpr FunctionQualifiers volatileRefNoexcept{
140+
.isVolatile = true,
141+
.isReferenceQualified = true,
142+
.isNoexcept = true};
142143
constexpr FunctionQualifiers cvRefNoexcept{
143144
.isConst = true,
144145
.isVolatile = true,
145-
.isRef = true,
146+
.isReferenceQualified = true,
147+
.isNoexcept = true};
148+
constexpr FunctionQualifiers constRvalueRefNoexcept{
149+
.isConst = true,
150+
.isRvalueReferenceQualified = true,
146151
.isNoexcept = true};
147-
constexpr FunctionQualifiers constRvalueRefNoexcept{.isConst = true, .isRvalueRef = true, .isNoexcept = true};
148152
constexpr FunctionQualifiers volatileRvalueRefNoexcept{
149153
.isVolatile = true,
150-
.isRvalueRef = true,
154+
.isRvalueReferenceQualified = true,
151155
.isNoexcept = true};
152156
constexpr FunctionQualifiers cvRvalueRefNoexcept{
153157
.isConst = true,
154158
.isVolatile = true,
155-
.isRvalueRef = true,
159+
.isRvalueReferenceQualified = true,
156160
.isNoexcept = true};
157161
}
158162

@@ -161,11 +165,11 @@ namespace Traits
161165
TRAITS_LIB_CREATE_SPECIALIZATION(volatile, {.isVolatile = true})
162166
TRAITS_LIB_CREATE_SPECIALIZATION(const volatile, Detail::cvQualified)
163167

164-
TRAITS_LIB_CREATE_SPECIALIZATION(&, {.isRef = true})
168+
TRAITS_LIB_CREATE_SPECIALIZATION(&, {.isReferenceQualified = true})
165169
TRAITS_LIB_CREATE_SPECIALIZATION(const&, Detail::constRef)
166170
TRAITS_LIB_CREATE_SPECIALIZATION(volatile&, Detail::volatileRef)
167171
TRAITS_LIB_CREATE_SPECIALIZATION(const volatile&, Detail::cvRef)
168-
TRAITS_LIB_CREATE_SPECIALIZATION(&&, {.isRvalueRef = true})
172+
TRAITS_LIB_CREATE_SPECIALIZATION(&&, {.isRvalueReferenceQualified = true})
169173
TRAITS_LIB_CREATE_SPECIALIZATION(const&&, Detail::constRvalueRef)
170174
TRAITS_LIB_CREATE_SPECIALIZATION(volatile&&, Detail::volatileRvalueRef)
171175
TRAITS_LIB_CREATE_SPECIALIZATION(const volatile&&, Detail::cvRvalueRef)

test/main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "test_function_traits.hpp"
2+
#include "readme_example.hpp"
23

34
#include <gtest/gtest.h>
45

test/readme_example.hpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#include <traits/functions.hpp>
2+
3+
#include <gtest/gtest.h>
4+
5+
#include <type_traits>
6+
7+
namespace Detail
8+
{
9+
auto lambda = [](int x) {
10+
return x * 2;
11+
};
12+
13+
struct FunctionObject
14+
{
15+
int operator()(double x) const
16+
{
17+
return static_cast<int>(x);
18+
}
19+
20+
std::string memberFunction(double x) const&
21+
{
22+
return std::to_string(x);
23+
}
24+
};
25+
26+
double freeFunction(double x)
27+
{
28+
return x * 2.0;
29+
}
30+
}
31+
32+
TEST(ReadmeExample, ReadmeFunctionExampleIsCorrect)
33+
{
34+
35+
using namespace Traits;
36+
37+
// Example of using FunctionTraits with a lambda
38+
auto lambda = [](std::string const& x, std::size_t y) noexcept {
39+
return x.size() + y;
40+
};
41+
using LambdaTraits = FunctionTraits<decltype(lambda)>;
42+
43+
static_assert(LambdaTraits::arity == 2, "Lambda should have arity 1");
44+
static_assert(std::is_same_v<LambdaTraits::ReturnType, std::size_t>, "Lambda should return int");
45+
static_assert(std::is_same_v<LambdaTraits::Argument<0>, std::string const&>, "Lambda should take int as argument");
46+
static_assert(std::is_same_v<LambdaTraits::Argument<1>, std::size_t>, "Lambda should take size_t as argument");
47+
static_assert(
48+
std::is_same_v<LambdaTraits::ArgumentDecayed<0>, std::string>, "Lambda should take size_t as argument");
49+
static_assert(std::is_same_v<LambdaTraits::ArgsTuple, std::tuple<std::string const&, std::size_t>>);
50+
static_assert(std::is_same_v<LambdaTraits::ArgsTupleDecayed, std::tuple<std::string, std::size_t>>);
51+
static_assert(LambdaTraits::qualifiers.isConst, "Lambda is not mutable");
52+
static_assert(!LambdaTraits::qualifiers.isVolatile, "Lambda is not volatile");
53+
static_assert(LambdaTraits::qualifiers.isNoexcept, "Lambda is noexcept");
54+
static_assert(!LambdaTraits::qualifiers.isReferenceQualified, "Lambda is not reference qualified");
55+
static_assert(!LambdaTraits::qualifiers.isRvalueReferenceQualified, "Lambda is not rvalue reference qualified");
56+
static_assert(
57+
std::is_same_v<LambdaTraits::StandardFunctionType, std::function<std::size_t(std::string const&, std::size_t)>>,
58+
"Standard function type should match");
59+
static_assert(
60+
std::is_same_v<LambdaTraits::StandardFunctionTypeDecayed, std::function<std::size_t(std::string, std::size_t)>>,
61+
"Standard function type decayed should match");
62+
}

0 commit comments

Comments
 (0)