Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 295
zennez Avatar asked Oct 25 '25 14:10

zennez


2 Answers

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.

like image 73
Anoop Rana Avatar answered Oct 27 '25 09:10

Anoop Rana


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 {}; }
like image 25
user17732522 Avatar answered Oct 27 '25 10:10

user17732522



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!