How to work around "function template has already been defined" when using std::enable_if with constexpr method

65 Views Asked by At

When using a constexpr method as the argument of std::enable_if_t, old MSVC compilers complain about "function template has already been defined". G++ and newer MSVC compilers accept that. How I can make that work also with old MSCV compilers?

Example code:

#include <climits>
#include <iostream>
#include <type_traits>

template <typename NumberType>
constexpr auto doBitCountsMatch(const int f_bitCount) -> bool {

  return (static_cast<int>(CHAR_BIT * sizeof(NumberType)) == f_bitCount);
}

template <typename NumberType, int bitCount>
auto test()
    -> std::enable_if_t<doBitCountsMatch<NumberType>(bitCount), NumberType> {
  std::cout << "Bit counts match." << std::endl;

  return 0;
}

template <typename NumberType, int bitCount>
auto test()
    -> std::enable_if_t<!doBitCountsMatch<NumberType>(bitCount), NumberType> {
  std::cout << "Bit counts don't match." << std::endl;

  return 0;
}

int main() {
  int number = 0;

  test<decltype(number), 32>();
  return 0;
}

And here in Compiler Explorer: https://godbolt.org/z/15PnPhvo8: MSVC 19.14 rejects the code, MSVC 19.33 accepts it. Why do the old compilers reject the code?

1

There are 1 best solutions below

3
Jarod42 On BEST ANSWER

You might use std::enable_if_t as template parameter instead:

template <typename NumberType, int bitCount,
          std::enable_if_t<doBitCountsMatch<NumberType>(bitCount), int> = 0>
auto test() -> NumberType
{
  std::cout << "Bit counts match." << std::endl;

  return 0;
}

template <typename NumberType, int bitCount,
          std::enable_if_t<!doBitCountsMatch<NumberType>(bitCount), int> = 0>
auto test() -> NumberType
{
  std::cout << "Bit counts don't match." << std::endl;

  return 0;
}

Demo