Home > other >  Constexpr function evaluation on a template parameter object (MSVC vs clang/gcc)
Constexpr function evaluation on a template parameter object (MSVC vs clang/gcc)

Time:07-25

As I understand it, the following should be valid C 20:

template<int i> struct A {};

struct B
{
  constexpr int one() const { return 1; }
};

template<B b> A<b.one()> f() { return {}; }

void test()
{
  f<B{}>();
}

MSVC does not like this (Visual Studio 2022, but godbolt appears to show all versions failing in some way, including an ICE for v19.28):

error C2672: 'f': no matching overloaded function found
error C2770: invalid explicit template argument(s) for 'A<'function'> f(void)'

Both clang and gcc accept it though.

As a workaround, wrapping the function evaluation works fine:

template<B b>
struct WrapOne
{
  static constexpr int value = b.one();
};

template<B b> A<WrapOne<b>::value> f() { return {}; }

Wrapping via an inline constexpr variable also works:

template<B b> inline constexpr auto one_v = b.one();
template<B b> A<one_v<b>> f() { return {}; }

I'm assuming that this is a bug in MSVC? I couldn't find anything relevant on the MS Developer Community site, but it feels like a pretty fundamental thing that other people must have come across.

Any other clever workarounds?

CodePudding user response:

Yes, seems like a bug to me as well.

The parser seems to have a problem specifically with the member function call via . in the template argument. It works when using ->:

template<B b> A<(&b)->one()> f() { return {}; }

CodePudding user response:

MSVC is wrong in rejecting the code as the program is well-formed since b.one() is a valid non-type template argument.

This bug has been reported here.

  • Related