我需要使一个函数只接受传递给它的参数的每个std::pair
的第一个值。传递的值不是std::pair
类型的值将不加改变地使用。我的以下解决方案仅适用于带有两个参数的函数。我需要知道如何将它推广到任何数量的传递参数。
#include <type_traits>
template <typename T, typename = void>
struct has_first_type : std::false_type { };
template <typename T>
struct has_first_type<T, std::void_t<typename T::first_type>> : std::true_type { };
template <typename R, typename T, typename U, typename = void> struct act_on_first;
template <typename R, typename T, typename U>
struct act_on_first<R, T, U, std::enable_if_t<has_first_type<T>::value && has_first_type<U>::value>> {
template <typename F>
static R execute (const T& t, const U& u, F f) {
return f(t.first, u.first);
}
};
template <typename R, typename T, typename U>
struct act_on_first<R, T, U, std::enable_if_t<has_first_type<T>::value && !has_first_type<U>::value>> {
template <typename F>
static R execute (const T& t, const U& u, F f) {
return f(t.first, u);
}
};
template <typename R, typename T, typename U>
struct act_on_first<R, T, U, std::enable_if_t<!has_first_type<T>::value && has_first_type<U>::value>> {
template <typename F>
static R execute (const T& t, const U& u, F f) {
return f(t, u.first);
}
};
template <typename R, typename T, typename U>
struct act_on_first<R, T, U, std::enable_if_t<!has_first_type<T>::value && !has_first_type<U>::value>> {
template <typename F>
static R execute (const T& t, const U& u, F f) {
return f(t, u);
}
};
struct foo {
template <typename... Args>
std::size_t operator()(Args&&...) { return sizeof...(Args); } // Simple example only.
};
template <typename T, typename U>
std::size_t bar (const T& t, const U& u) {
return act_on_first<std::size_t, T, U>::execute(t, u, foo());
}
// Testing
#include <iostream>
int main() {
std::pair<int, bool> k = {3, true};
std::pair<int, char> m = {5, 't'};
std::cout << bar(k,m) << '\n'; // 2
std::cout << bar(k,5) << '\n'; // 2
std::cout << bar(3,m) << '\n'; // 2
std::cout << bar(3,5) << '\n'; // 2
}
答案 0 :(得分:7)
写一个变换器,它可以为你提供.first
或者只返回它的参数:
template <typename T> T const& take_first(T const& x) { return x; }
template <typename T, typename U>
T const& take_first(std::pair<T, U> const& p) { return p.first; }
template <typename... Args>
std::size_t bar(Args const&... args) {
return foo{}(take_first(args)...);
}