Skip to content

Commit

Permalink
perf: 优化 signature 实现
Browse files Browse the repository at this point in the history
* 容器全部放入主模板
* 去掉多余 std::invoke
  • Loading branch information
zsien committed Feb 7, 2021
1 parent 1e8df90 commit a70894d
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 27 deletions.
10 changes: 4 additions & 6 deletions include/dbusx/method.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,12 @@ struct method<F> {

// using out_type = OUT;

// std::array<std::string_view>{"i", "t", "as"}
static constexpr auto in_arr = std::invoke([] {
return std::array{std::string_view(signature<IN>.cbegin(), signature<IN>.size())...};
});
// const char *const *{"i", "t", "as"}
static constexpr auto in_arr = signature_nt_arr<IN...>.data();

// std::string_view{"as"}
static constexpr auto out_str = std::invoke(
[] { return std::string_view(signature<OUT>.cbegin(), signature<OUT>.size()); });
static constexpr auto out_str =
std::string_view(signature<OUT>.cbegin(), signature<OUT>.size());

static vtable::method vtable() {
// std::vector<std::string> in_signatures;
Expand Down
38 changes: 20 additions & 18 deletions include/dbusx/signature.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
namespace dbusx {

template <typename T>
constexpr auto signature_basic = std::invoke([] {
constexpr auto signature_single = std::invoke([] {
using Type = std::remove_cvref_t<T>;

if constexpr (std::is_same<Type, char>::value) {
Expand Down Expand Up @@ -45,37 +45,39 @@ constexpr auto signature_basic = std::invoke([] {
// return std::array{'o'};
//} else if constexpr (std::is_same<Type, dbus_signature>::value) {
// return std::array{'g'};
} else if constexpr (is_vector<Type>::value) {
// array
return concat(std::array{'a'}, signature_single<typename Type::value_type>);
} else if constexpr (is_unordered_map<Type>::value) {
// dict
return concat(std::array{'{'},
signature_single<typename Type::key_type>,
signature_single<typename Type::mapped_type>,
std::array{'}'});
} else if constexpr (is_tuple<Type>::value) {
// struct
// top-level cv-qualifiers and reference removed
return signature_single<Type>;
} else if constexpr (std::is_same<Type, std::any>::value) {
return std::array{'v'};
} else {
static_assert(always_false_v<Type>, "unsupported type");
}
});

// array
template <typename T>
constexpr auto signature_basic<std::vector<T>> = std::invoke([] {
return concat(std::array{'a'}, signature_basic<T>);
});

// dict
template <typename F, typename S>
constexpr auto signature_basic<std::unordered_map<F, S>> = std::invoke([] {
return concat(std::array{'{'}, signature_basic<F>, signature_basic<S>, std::array{'}'});
});

// struct
template <typename... T>
constexpr auto signature_basic<std::tuple<T...>> = std::invoke([] {
return concat(std::array{'('}, signature_basic<T>..., std::array{')'});
});
constexpr auto signature_single<std::tuple<T...>> = concat(std::array{'('}, signature_single<T>..., std::array{')'});

template <typename... T>
constexpr auto signature = std::invoke([] { return concat(signature_basic<T>...); });
constexpr auto signature = concat(signature_single<T>...);

// signature with null-terminated
template <typename T>
constexpr auto signature_nt = std::invoke([] { return concat(signature<T>, std::array{'\0'}); });
constexpr auto signature_nt = concat(signature<T>, std::array{'\0'});

template <typename... T>
constexpr auto signature_nt_arr = std::array{signature_nt<T>.data()...};

template <typename T>
auto unwrap_type() {
Expand Down
28 changes: 25 additions & 3 deletions include/dbusx/utils.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#ifndef DBUSX_UTILS_H
#define DBUSX_UTILS_H

#include <type_traits>
#include <vector>
#include <unordered_map>
#include <tuple>
#include <array>
#include <utility>

Expand All @@ -15,12 +19,30 @@
template <typename T>
inline constexpr bool always_false_v = false;

template <typename T>
struct is_vector : public std::false_type {};

template <typename T>
struct is_vector<std::vector<T>> : public std::true_type {};

template <typename T>
struct is_unordered_map : public std::false_type {};

template <typename K, typename V>
struct is_unordered_map<std::unordered_map<K, V>> : public std::true_type {};

template <typename T>
struct is_tuple : public std::false_type {};

template <typename... T>
struct is_tuple<std::tuple<T...>> : public std::true_type {};

// Expansion pack
template <std::size_t N1, std::size_t... I1, std::size_t N2, std::size_t... I2>
static constexpr std::array<char, N1 + N2> concat(const std::array<char, N1> &a1,
const std::array<char, N2> &a2,
std::index_sequence<I1...> /*unused*/,
std::index_sequence<I2...> /*unused*/) {
std::index_sequence<I1...> /* unused */,
std::index_sequence<I2...> /* unused */) {
return {a1[I1]..., a2[I2]...};
}

Expand All @@ -32,7 +54,7 @@ static constexpr auto concat(const std::array<char, N1> &a1) {
template <std::size_t N1, std::size_t N2, std::size_t... Ns>
static constexpr auto concat(const std::array<char, N1> &a1,
const std::array<char, N2> &a2,
const std::array<char, Ns> &... as) {
const std::array<char, Ns> &...as) {
return concat(concat(a1, a2, std::make_index_sequence<N1>{}, std::make_index_sequence<N2>{}),
as...);
}
Expand Down

0 comments on commit a70894d

Please sign in to comment.