Tengo una tupla y estoy intentando llamar a initialize () para cada objeto dentro de la tupla. Ahora, es posible que algunos objetos no contengan esa función. Sé que puedo hacer que eso funcione usando la característica C ++ 20 requiere para verificar si una clase contiene una función determinada. Desafortunadamente, estoy usando MSVC y todavía no lo admite.

¿Es posible escribir eso de otra manera? Puedo usar C ++ 20 pero debería compilarse en MSVC

template <class... Args>
struct CustomTuple : std::tuple<Args...> {
  // Calls "initialize() for each item inside the tuple if that function exists"
  template <std::size_t I = 0>
  auto initialize() {
       std::decay_t<decltype(std::get<I>(*this))> item;
       constexpr bool has_initialize = requires() { // doesnt't work on MSVC
           item.initialize(); 
       };
       if constexpr (has_initialize) {
           std::get<I>(*this).initialize();
       }
       if constexpr (I + 1 != sizeof...(Args)) {
           initialize<I + 1>();
    }
  }
};
3
Gärtner 11 jul. 2021 a las 18:01

2 respuestas

En su lugar, puede definir su propio concepto.

template<typename T>
concept has_initialize = requires(T a) {
    a.initialize();
};

template <class... Args>
struct CustomTuple : std::tuple<Args...> {
  // Calls "initialize() for each item inside the tuple if that function exists"
  template <std::size_t I = 0>
  auto initialize() {
       std::decay_t<decltype(std::get<I>(*this))> item;
       if constexpr (has_initialize<decltype(item)>) {
           std::get<I>(*this).initialize();
       }
       if constexpr (I + 1 != sizeof...(Args)) {
           initialize<I + 1>();
    }
  }
};

https://godbolt.org/z/rvhPPsqcz

0
김선달 11 jul. 2021 a las 15:23

Usando las características de C ++ 17 y escupiendo el problema en funciones más pequeñas:

template<typename T, typename U = void>
struct has_inistialize_t : std::false_type {};

template<typename T>
struct has_inistialize_t<T, std::void_t<decltype(
std::declval<T>().initialize())>> : std::true_type {};

template<typename T>
void tryInitialize_helper(T&& x, std::true_type)
{
    std::forward<T>(x).initialize();
}

template<typename T>
void tryInitialize_helper(T&& x, std::false_type)
{}

template<typename T>
void initialize_if_possible(T&& x)
{
    tryInitialize_helper(std::forward<T>(x), has_inistialize_t<T>{});
}

template<typename ...Ts>
void initilize_each_if_possible(std::tuple<Ts...>& t)
{
    std::apply([](auto&... args){(initialize_if_possible(args), ...);}, t);
}

https://godbolt.org/z/vcEnjY7vE

0
Marek R 12 jul. 2021 a las 17:35