1

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.

Dr. Gut
  • 2,053
  • 7
  • 26
  • Is your question, "does the standard not allow this?", or "are there plans to add this feature?"? – cigien May 07 '20 at 18:07
  • @cigien: My question is the latter: are there ongoing efforts/plans to add this feature or similar feature to the language? – Dr. Gut May 07 '20 at 19:34

1 Answers1

1

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

Amir Kirsh
  • 12,564
  • 41
  • 74
  • Thanks. I see. You generalized the idea. In case of `bool` we could simplify with `std::bool_constant` ([example](https://godbolt.org/z/5NE5RS)), but not if the variable template is of any literal type. – Dr. Gut May 07 '20 at 19:56