N Strahl
N Strahl

Reputation: 85

How to deal with template const and non-const parameters?

I have a Template function taking in const types such as:

template <class T, class U>
    void process(const T& v1, const U& v2)
    {
      //do some things
      verify(v1);
      verify(v2);
    }

Then the verify function checks the Type for T using if constexpr as follows: (The function also returns the variable. I set it to auto for the purpose of this question)

template <class T>
    auto verify(const T& t)
    {
      if constexpr (is_same_v<T, int>)
          return t;
      if constexpr (is_same_v<T, string>)
          return t;
      if constexpr (is_same_v<T, double*>)
          return t;
      else
          static_assert(false, "Type not allowed");
    }

if the type is not found it will trigger a compilation error. This all works very fine but the problem is I would like to make v2 a non-const U& parameter. This triggers the static_assert and I don't know why. I also set all parameters in both functions to non-const but I still get the same error. All I really want is to pass the arguments by reference. Can anyone give me some hints? Thanks in advance.

Upvotes: 0

Views: 1134

Answers (2)

Aykhan Hagverdili
Aykhan Hagverdili

Reputation: 29955

A better way of doing that would be to static_assert some type trait:

#include <string>
#include <type_traits>

template <class T, class... Y>
inline bool constexpr is_one_of =
    (std::is_same_v<std::decay_t<T>, std::decay_t<Y>> || ...);

template <class T>
void verify() {
  static_assert(is_one_of<T, int, std::string, double*>);
}

template <class T, class U>
void process(T const& v1, U const& v2) {
  verify<T>();
  verify<U>();

  // ...
}

Upvotes: 1

MSalters
MSalters

Reputation: 179779

This is one of those things you'd need to know.

The form you're looking for is

template <class T> auto verify(T&& t) {

The reason is that T can be const U, a const-qualified type. The double && is necessary for rvalue references.

You probably want std::is_same_v<std::remove_cv_t<T>>, ...

And to simply things:

template <class T> auto verify(T&& t)
{
  using baseT = std::remove_cv_t<T>;
  static_assert(is_same_v<baseT, int> || 
                is_same_v<baseT, string> ||
                is_same_v<baseT, double*>);
  return t;
}

Upvotes: 2

Related Questions