Home > Mobile >  Any way to check count of template parameters at compile time?
Any way to check count of template parameters at compile time?

Time:07-27

Is there any way to check number of template parameters and compile time? I would like to do this (this is not real code):

template<typename... Types>
class Foo
{
    // Enable this if count of 'Types' is 1.
    Types[0] Bar()
    {
        return Types[0]{};
    }
    
    // Enable this otherwise.
    std::variant<Types> Bar()
    {
        return std::variant<Types>{};
    }

};

Is there any way to achieve this?

CodePudding user response:

Not like that, at least not easily. You can probably add some helper struct that defines a type with if constexpr and sizeof...() and then use helper::return_type or seomthing.

But I think this calls for template specialization:

#include <variant>

template<typename... Types>
class Foo
{
    std::variant<Types...> Bar()
    {
        return {};
    }

};

// Specialize for just one Type
template<typename Type>
class Foo<Type>
{
    Type Bar()
    {
        return {};
    }
};

CodePudding user response:

One option is to add a template parameter and then leverage constexpr if to check if the pack is empty or not like

template<typename first_t, typename... rest_t>
class Foo
{
    auto Bar()
    {
        if constexpr (sizeof...(rest_t) == 0)
            return first_t{};
        else
            return std::variant<first_t, rest_t...>{};
    }
};

CodePudding user response:

It's not too hard to create a alias template for the type by specializing a helper type:

template<class...Ts>
struct ReturnTypeHelper : std::type_identity<std::variant<Ts...>> {};

template<class T>
struct ReturnTypeHelper<T> : std::type_identity<T> {};

template<class...Ts>
using ReturnType = typename ReturnTypeHelper<Ts...>::type;

template<typename... Types>
class Foo
{
public:
    auto Bar()
    {
        return ReturnType<Types...>{};
    }
};

static_assert(std::is_same_v<decltype(std::declval<Foo<int>>().Bar()), int>);
static_assert(std::is_same_v<decltype(std::declval<Foo<int,float>>().Bar()), std::variant<int, float>>);
  •  Tags:  
  • c
  • Related