//https://stackoverflow.com/questions/76824177/ordering-multiple-function-calls-during-compile-time
#include <cassert>
#include <iostream>
#include <type_traits>
#include <variant>
#include <string>
#include <iomanip>
using namespace std::string_literals;
// Using a variant type to specify the priority of types
// the actual variant is not used in implementation
using variant_t = std::variant<std::string, int, double>; // order in variant is order in which to call functions too
// declare functions first before templates.
void do_work(int value)
{
std::cout << "do_work(int " << value << ")\n";
}
void do_work(double value)
{
std::cout << "do_work(double " << value << ")\n";
}
void do_work(const std::string& value)
{
std::cout << "do_work(string " << std::quoted(value) << ")\n";
}
// recursive part of looping over both the variant types
// and the argument types
namespace details
{
template<typename variant_type_t, typename arg_t>
constexpr std::size_t handle(arg_t arg)
{
if constexpr (std::is_same_v<variant_type_t, arg_t>)
{
do_work(arg); // <== this requires all overloads of function to be already known, before template is instantiated
return 1ul;
}
else
{
return 0ul;
}
}
template<std::size_t variant_index_v, typename... args_t>
static constexpr std::size_t do_work_for_variant_type(args_t&&... args)
{
using variant_type_t = std::remove_reference_t<decltype(std::get<variant_index_v>(variant_t{}))>;
std::size_t items_handled{0ul};
((items_handled += handle<variant_type_t>(args)),...);
// recurse
if constexpr ((variant_index_v+1ul) < std::variant_size_v<variant_t>)
{
items_handled += do_work_for_variant_type<variant_index_v + 1ul>(std::forward<args_t>(args)...);
}
return items_handled;
}
}
template<typename... args_t>
static constexpr void do_work_in_order_of_priority(args_t&&... args)
{
constexpr auto number_of_items_to_handle = sizeof...(args_t);
// todo figure out how to make items_handled constexpr too
auto items_handled = details::do_work_for_variant_type<0ul>(std::forward<args_t>(args)...);
assert(number_of_items_to_handle == items_handled);
}
int main()
{
do_work_in_order_of_priority(1, "string 1"s, 1.0, "string 2"s);
return 0;
}