Home > OS >  How do I use std::is_same_v in a using statement?
How do I use std::is_same_v in a using statement?

Time:02-05

Consider the following code:

template<typename T>
using IsInt = std::is_same<T, int>::value;

template<class SrcType, class DstType>
constexpr DstType As(SrcType val) {
  if constexpr (IsInt<SrcType>) return val;
}

This code compiles fine with C 17 but if I use std::is_same_v<...> instead of std::is_same<...>::value, then the GCC complains:

error: 'std::is_same_v<_Tp, _Up>' in namespace 'std' does not name a template type

I'm guessing the error is due to the fact that std::is_same_v is declared constexpr. How can I fix it (while maintaining the type alias)?

CodePudding user response:

Actually, the sample code doesn't compile.

#include <type_traits>

template<typename T>
using IsInt = std::is_same<T, int>::value;

The using declaration here is for type aliases. In C 17, it would have to be

template<typename T>
using IsInt = typename std::is_same<T, int>::value;

However, this is incorrect, because std::is_same<T, int>::value isn't a type, it's a value, and we want IsInt to be a value as well.

(In C 20, because only typenames are syntactically correct for the right hand side of this kind of using expression, the use of the typename keyword is no longer required here, but it's still creating a type alias, which is not what's intended.)

So what we actually want is the same sort of helper that C 17 uses for its _v convenience members:

template<typename T>
inline constexpr bool IsInt = std::is_same<T, int>::value;

The following also works:

template<typename T>
inline constexpr bool IsInt = std::is_same_v<T, int>;

inline assuming that this lives in a header and we want to use this same definition in multiple translation units, constexpr because it's known at compile time and this lets us use it in if constexpr or other purposes.

  •  Tags:  
  • Related