Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Call template-function with types in a tuple (not values)

I would like to call a template function with no arguments for each type in a tuple. The code below shows exactly what the intention is.

My solution involves making a dummy instance of DataGroup(). I’d like to avoid this, as the types may not have a default constructor.

I’ve attempted to use std::declval<DataGroup>() instead, this results in
'std::declval': Symbol involving type with internal linkage not defined (in msvc).

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#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
}



My preferred solution, based on two of the answers together:

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>()
    {
        // ...
    });
}

>Solution :

You can pass in std::type_identity which is always default-constructible

#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>());
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading