|
3 | 3 | #include <tuple>
|
4 | 4 | #include <type_traits>
|
5 | 5 |
|
6 |
| -namespace CppInject |
7 |
| -{ |
8 |
| - namespace detail |
9 |
| - { |
10 |
| - template <class T> |
11 |
| - T pretendToCreateAnything(); |
| 6 | +namespace CppInject { |
| 7 | +namespace detail { |
| 8 | +template <class T> |
| 9 | +T pretendToCreateAnything(); |
12 | 10 |
|
13 |
| - template <typename T, int ArgIndex> |
14 |
| - struct OverloadResolutionHelper { |
15 |
| - friend auto functionWithReturnTypeOfArg(OverloadResolutionHelper<T, ArgIndex>); |
16 |
| - }; |
| 11 | +template <typename T, int ArgIndex> |
| 12 | +struct OverloadResolutionHelper { |
| 13 | + friend auto functionWithReturnTypeOfArg( |
| 14 | + OverloadResolutionHelper<T, ArgIndex>); |
| 15 | +}; |
17 | 16 |
|
18 |
| - template <typename T, typename TArg, int ArgIndex, |
19 |
| - // do not find copy / move constructor |
20 |
| - typename = typename std::enable_if_t<!std::is_same_v< |
21 |
| - std::remove_cv_t<std::remove_reference_t<T>>, |
22 |
| - std::remove_cv_t<std::remove_reference_t<TArg>>>>> |
23 |
| - struct FunctionWithReturnTypeOfArgWrapper { |
24 |
| - friend auto functionWithReturnTypeOfArg(OverloadResolutionHelper<T, ArgIndex>) { |
25 |
| - return pretendToCreateAnything<TArg>(); |
26 |
| - } |
27 |
| - }; |
| 17 | +template <typename T, typename TArg, int ArgIndex, |
| 18 | + // do not find copy / move constructor |
| 19 | + typename = typename std::enable_if_t< |
| 20 | + !std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, |
| 21 | + std::remove_cv_t<std::remove_reference_t<TArg>>>>> |
| 22 | +struct FunctionWithReturnTypeOfArgWrapper { |
| 23 | + friend auto functionWithReturnTypeOfArg( |
| 24 | + OverloadResolutionHelper<T, ArgIndex>) { |
| 25 | + return pretendToCreateAnything<TArg>(); |
| 26 | + } |
| 27 | +}; |
28 | 28 |
|
29 |
| - // The templated conversion operator is enabled for the correct argument using SFINAE |
30 |
| - template <typename T, int ArgIndex> |
31 |
| - struct ToConstructorArgTypeConvertible { |
32 |
| - template <typename TArg, int = sizeof(FunctionWithReturnTypeOfArgWrapper<T, TArg, ArgIndex>)> |
33 |
| - operator TArg& (); |
34 |
| - template <typename TArg, int = sizeof(FunctionWithReturnTypeOfArgWrapper<T, TArg, ArgIndex>)> |
35 |
| - operator TArg&& (); |
36 |
| - }; |
| 29 | +// The templated conversion operator is enabled for the correct argument using |
| 30 | +// SFINAE |
| 31 | +template <typename T, int ArgIndex> |
| 32 | +struct ToConstructorArgTypeConvertible { |
| 33 | + template <typename TArg, |
| 34 | + int = sizeof(FunctionWithReturnTypeOfArgWrapper<T, TArg, ArgIndex>)> |
| 35 | + operator TArg&(); |
| 36 | + template <typename TArg, |
| 37 | + int = sizeof(FunctionWithReturnTypeOfArgWrapper<T, TArg, ArgIndex>)> |
| 38 | + operator TArg&&(); |
| 39 | +}; |
37 | 40 |
|
38 |
| - template <typename T, int... ArgIndices> |
39 |
| - constexpr size_t numberOfConstructorArgsIntern( |
40 |
| - // overload resolution will prefer this when called with 0 |
41 |
| - int, |
42 |
| - // uses SFINAE to enable this for the correct number of arguments only |
43 |
| - decltype(T(ToConstructorArgTypeConvertible<T, ArgIndices>{}...))* = nullptr |
44 |
| - ) { |
45 |
| - return sizeof...(ArgIndices); |
46 |
| - } |
| 41 | +template <typename T, int... ArgIndices> |
| 42 | +constexpr size_t numberOfConstructorArgsIntern( |
| 43 | + // overload resolution will prefer this when called with 0 |
| 44 | + int, |
| 45 | + // uses SFINAE to enable this for the correct number of arguments only |
| 46 | + decltype(T(ToConstructorArgTypeConvertible<T, ArgIndices>{}...))* = |
| 47 | + nullptr) { |
| 48 | + return sizeof...(ArgIndices); |
| 49 | +} |
47 | 50 |
|
48 |
| - template <typename T, int... ArgIndices> |
49 |
| - constexpr size_t numberOfConstructorArgsIntern(char) { // overload resolution will disfavor this overload when called with 0 |
50 |
| - return numberOfConstructorArgsIntern<T, ArgIndices..., sizeof...(ArgIndices)>(0); |
51 |
| - } |
| 51 | +template <typename T, int... ArgIndices> |
| 52 | +constexpr size_t numberOfConstructorArgsIntern( |
| 53 | + char) { // overload resolution will disfavor this overload when called with |
| 54 | + // 0 |
| 55 | + return numberOfConstructorArgsIntern<T, ArgIndices..., sizeof...(ArgIndices)>( |
| 56 | + 0); |
| 57 | +} |
52 | 58 |
|
53 |
| - template <typename T, typename U> |
54 |
| - struct ConstructorArgsAsTupleIntern; |
| 59 | +template <typename T, typename U> |
| 60 | +struct ConstructorArgsAsTupleIntern; |
55 | 61 |
|
56 |
| - template <typename T, int... ArgIndices> |
57 |
| - struct ConstructorArgsAsTupleIntern<T, std::integer_sequence<int, ArgIndices...>> { |
58 |
| - using TupleType = std::tuple<decltype(functionWithReturnTypeOfArg(OverloadResolutionHelper<T, ArgIndices>{}))... > ; |
59 |
| - }; |
60 |
| - } |
| 62 | +template <typename T, int... ArgIndices> |
| 63 | +struct ConstructorArgsAsTupleIntern<T, |
| 64 | + std::integer_sequence<int, ArgIndices...>> { |
| 65 | + using TupleType = std::tuple<decltype(functionWithReturnTypeOfArg( |
| 66 | + OverloadResolutionHelper<T, ArgIndices>{}))...>; |
| 67 | +}; |
| 68 | +} // namespace detail |
61 | 69 |
|
62 |
| - /// <summary> |
63 |
| - /// Get the number of arguments of a constructor |
64 |
| - /// </summary> |
65 |
| - /// <typeparam name="T">The type of the class with the constructor</typeparam> |
66 |
| - /// <returns>The number of arguments of the constructor with the lowest number of arguments</returns> |
67 |
| - template <typename T> |
68 |
| - constexpr auto numberOfConstructorArgs() { |
69 |
| - return detail::numberOfConstructorArgsIntern<T>(0); |
70 |
| - } |
71 |
| - |
72 |
| - /// <summary> |
73 |
| - /// Get constructor arguments as a tuple. |
74 |
| - /// Note that qualifiers and references are dropped. |
75 |
| - /// </summary> |
76 |
| - /// <typeparam name="T"></typeparam> |
77 |
| - template <typename T> |
78 |
| - using ConstructorArgsAsTuple = |
79 |
| - typename detail::ConstructorArgsAsTupleIntern<T, |
80 |
| - std::make_integer_sequence<int, numberOfConstructorArgs<T>()>>::TupleType; |
| 70 | +/// <summary> |
| 71 | +/// Get the number of arguments of a constructor |
| 72 | +/// </summary> |
| 73 | +/// <typeparam name="T">The type of the class with the constructor</typeparam> |
| 74 | +/// <returns>The number of arguments of the constructor with the lowest number |
| 75 | +/// of arguments</returns> |
| 76 | +template <typename T> |
| 77 | +constexpr auto numberOfConstructorArgs() { |
| 78 | + return detail::numberOfConstructorArgsIntern<T>(0); |
81 | 79 | }
|
| 80 | + |
| 81 | +/// <summary> |
| 82 | +/// Get constructor arguments as a tuple. |
| 83 | +/// Note that qualifiers and references are dropped. |
| 84 | +/// </summary> |
| 85 | +/// <typeparam name="T"></typeparam> |
| 86 | +template <typename T> |
| 87 | +using ConstructorArgsAsTuple = typename detail::ConstructorArgsAsTupleIntern< |
| 88 | + T, |
| 89 | + std::make_integer_sequence<int, numberOfConstructorArgs<T>()>>::TupleType; |
| 90 | +} // namespace CppInject |
0 commit comments