c++ 使用元组中的类型(而不是值)调用模板函数

ippsafx7  于 2023-02-06  发布在  其他
关注(0)|答案(3)|浏览(179)

我想调用一个模板函数,对于元组中的每个类型都没有参数。下面的代码显示了它的意图。
我的解决方案涉及到创建一个DataGroup()的伪示例,我希望避免这种情况,因为类型可能没有默认构造函数。
我尝试使用std::declval<DataGroup>()代替,结果是'std::declval': Symbol involving type with internal linkage not defined(在msvc中)。

#pragma once
#include <tuple>

template<typename T>
void do_something_based_on_the_type()
{
    // ...
}

template<template <typename...> typename Tuple, typename... Ts>
void do_something_based_on_the_types_in_a_tuple(Tuple<Ts...>)
{
    (do_something_based_on_the_type<Ts>(), ...);
}

void some_code()
{
    struct Dataset1 {};
    struct Dataset2 {};
    struct Dataset3 {};
    using DataGroup = std::tuple<Dataset1, Dataset2, Dataset3>;

    do_something_based_on_the_types_in_a_tuple(DataGroup()); // -> ugly? requires a dummy instantiation of the tuple
}

我的首选解决方案,基于两个答案:

namespace internal
{

template<template <typename...> typename Tuple, typename TemplateFunc, typename... Ts>
void call_per_type_in_tuple(std::type_identity<Tuple<Ts...>>, TemplateFunc f)
{
    (f.template operator () < Ts > (), ...);
}

}

template<typename Tuple, typename TemplateFunc>
void call_foreach_tuple_type(TemplateFunc f)
{
    internal::call_per_type_in_tuple(std::type_identity<Tuple>(), std::forward<TemplateFunc>(f));
}

void example()
{
    struct Dataset1 {};
    struct Dataset2 {};
    struct Dataset3 {};
    using DataGroup = std::tuple<Dataset1, Dataset2, Dataset3>;

    call_foreach_tuple_type<DataGroup>([]<typename T>()
    {
        // ...
    });
}
xriantvc

xriantvc1#

可以传入始终可缺省构造的std::type_identity

#include <type_traits>

template<template <typename...> typename Tuple, typename... Ts>
void do_something_based_on_the_types_in_a_tuple(std::type_identity<Tuple<Ts...>>)
{
    (do_something_based_on_the_type<Ts>(), ...);
}

using DataGroup = std::tuple<Dataset1, Dataset2, Dataset3>;
do_something_based_on_the_types_in_a_tuple(std::type_identity<DataGroup>());
k2arahey

k2arahey2#

具有类模板专用化的变量:

#include <tuple>

template<typename T>
void do_something_based_on_the_type()
{
    // ...
}

template<typename x_Tuple>
class t_ForEachItem;

template<typename... x_Items>
class t_ForEachItem<::std::tuple<x_Items...>>
{
    public: static void
    Do(){ (do_something_based_on_the_type<x_Items>(), ...); }
};

void some_code()
{
    struct Dataset1 {};
    struct Dataset2 {};
    struct Dataset3 {};
    using DataGroup = std::tuple<Dataset1, Dataset2, Dataset3>;

    t_ForEachItem<DataGroup>::Do();
}

它也可以与函数调用一起使用:

template<typename x_Tuple>
void do_something_based_on_the_types_in_a_tuple()
{
   t_ForEachItem<x_Tuple>::Do();
}
...
do_something_based_on_the_types_in_a_tuple<DataGroup>();

通用变体:

#include <tuple>

template<typename x_Tuple>
class t_ForEachItem;

template<typename... x_Items>
class t_ForEachItem<::std::tuple<x_Items...>>
{
    public: template<typename x_Fun> static void
    Do(x_Fun fun){ (fun.template operator ()<x_Items>(), ...); }
};

void some_code()
{
    struct Dataset1 {};
    struct Dataset2 {};
    struct Dataset3 {};
    using DataGroup = std::tuple<Dataset1, Dataset2, Dataset3>;

    t_ForEachItem<DataGroup>::Do([]<typename T>(){});
}

联机编译程序

6ojccjat

6ojccjat3#

我的解决方案是使用一个helper函数来进行类型推导,这个helper函数将获取一个指向DataGroup示例的指针,并使用它来推导元组中的类型。

template<typename T>
void do_something_based_on_the_type()
{
    // ...
}

template<typename T>
void do_something_based_on_the_types_in_a_tuple_helper(T* dataGroup)
{
    std::apply([](auto&&... args){ (do_something_based_on_the_type<decltype(args)>(), ...); }, *dataGroup);
}

void some_code()
{
    struct Dataset1 {};
    struct Dataset2 {};
    struct Dataset3 {};
    using DataGroup = std::tuple<Dataset1, Dataset2, Dataset3>;

    DataGroup dataGroup;
    do_something_based_on_the_types_in_a_tuple_helper(&dataGroup);
}

相关问题