How to pass a variable template as template argument

1.1k Views Asked by At

I am aware, that I can pass a class template as template argument like this:

template <template <class> class ClassTemplate>
void foo()
{
    ClassTemplate<int> x;
}

int main()
{
    foo<std::optional>();
}

But suppose I have a variable template:

template <class T>
constexpr bool IsBig = sizeof(T) >= sizeof(void*);

How can I pass it as a template argument? Is there a simple solution? I guess the language simply does not support it. This does not work:

template <template <class> bool VariableTemplate>         // fictional C++ syntax
void foo()
{
    bool b = VariableTemplate<int>;
}

int main()
{
    foo<IsBig>();
}

Is there an ongoing effort in the Standardization Committee to include the above syntax (or similar) into C++ as a new feature?

I found no simple solution. I guess that's why all type traits are currently represented by a class (with ...::type and ...::value members) in STL. I wanted to avoid to use classes as traits. For example the straightforward way to implement IsBig is a variable template.

1

There are 1 best solutions below

1
Amir Kirsh On

You cannot do that directly with a variable template, but there is a simple workaround:

template<class T>
constexpr bool IsBig = sizeof(T) >= sizeof(void*);

template<class T>
struct IsBigWrapperA {
    static constexpr auto value = IsBig<T>;

    constexpr operator decltype(value)() const {
        return value;
    }
};

template <template<class> class VariableTemplateWrapper>
void foo() {
    bool b = VariableTemplateWrapper<int>();
}

int main() {
    foo<IsBigWrapperA>();
}

We can then have a macro (yeah...) to allow a generic variable template wrapper:

#define CREATE_WRAPPER_FOR(VAR)                    \
  template<typename T>                             \
  struct VAR##Wrapper {                            \
      static constexpr auto value = VAR<T>;        \
      constexpr operator decltype(value)() const { \
          return value;                            \
      }                                            \
  };

// need to call the macro to create the wrapper
CREATE_WRAPPER_FOR(IsBig)

template<template<class> class VariableTemplateWrapper>
void foo() {
    bool b = VariableTemplateWrapper<int>();
}

int main() {
    foo<IsBigWrapper>();
}

Code: https://godbolt.org/z/gNgGhq