模板参数对象上的Constexpr函数求值(MSVC vs clang/gcc)

4

据我所了解,以下内容应该是符合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 不支持这种写法(指 Visual Studio 2022,但据 godbolt 显示所有版本都存在某些问题,包括 v19.28 出现 ICE):

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

无论是clang还是gcc都可以接受它。

作为一种解决方法,将函数评估包装起来就可以了。

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

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

使用内联的constexpr变量也可以进行包装:

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

我假定这是MSVC的一个bug?我在MS开发者社区网站上没有找到相关信息,但感觉这是其他人一定遇到过的非常基本的问题。

还有其他聪明的解决方法吗?

2个回答

3

MSVC错误地拒绝了这段代码,因为程序是完全成形的,由于b.one()是有效的非类型模板参数。

这个错误已经在这里报告了。


2

是的,我也觉得这似乎是一个错误。

解析器似乎在模板参数中使用.进行成员函数调用时出现了问题。当使用->时它可以正常工作:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接