Сначала вы можете принять произвольные типы Futures...
, а затем использовать SFINAE, чтобы ограничить их значением std::[shared_]future
:
template<class>
struct is_future_or_shared_future : std::false_type {};
template<class T>
struct is_future_or_shared_future<std::future<T>> : std::true_type {};
template<class T>
struct is_future_or_shared_future<std::shared_future<T>> : std::true_type {};
template<class... Futures, typename = std::enable_if_t<
std::conjunction_v<is_future_or_shared_future<Futures>...>>>
void foo(Futures&... args) {
// ...
}
Если вы хотите принять оба значения lvalue и rvalue, используйте ссылки пересылки:
template<class T>
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
template<class... Futures, typename = std::enable_if_t<
std::conjunction_v<is_future_or_shared_future<remove_cvref_t<Futures>>...>>>
void foo(Futures&&... args) {
// ...
}
Для доступа к внутреннему типу вы можете использовать класс черт:
template<class>
struct inner_type;
template<class T>
struct inner_type<std::future<T>> {
using type = T;
};
template<class T>
struct inner_type<std::shared_future<T>> {
using type = T;
};
и затем написать:
typename B = std::result_of_t<
F(typename inner_type<remove_cvref_t<Futures>>::type...)>;