延迟模板实例化中的编译器分歧:代码合规性与正确性判定
基类模板成员函数检测的编译器行为与标准合规性问题
我希望在基类未实现指定成员函数时触发static_assert,编写了如下C++代码:
#include<type_traits> template<typename T> struct AlwaysFalse : public std::false_type {}; struct B { template<typename S> void foo(){} }; template <typename T,typename S> struct A : T { auto foo(){ if constexpr (requires{ T::template foo<S>(); }) return 1; else static_assert(AlwaysFalse<A>::value, "foo is not implemented."); } }; int main() { A<B, double> a; a.foo(); }
这段代码在GCC 12.2中可以正常编译,但在Clang 16及开发版本中编译失败;如果将基类的foo改为非模板函数,Clang也能正常编译。
我有两个疑问:
- 哪个编译器的行为是正确的?我认为是GCC,因为基类的成员函数确实存在,不应该触发
static_assert。 - 上述代码是否符合C++标准?
另外我找到了一个兼容两种编译器的解决方案,修改requires表达式,在其中创建基类对象:
if constexpr (requires(T t){ t.template foo<S>(); })
相关测试场景说明:
- 模板版本:原代码场景,基类
foo为模板函数 - 非模板版本:基类
foo改为非模板函数的场景 - 兼容方案:修改
requires表达式后的代码场景
内容的提问来源于stack exchange,提问作者rath3t
相关产品推荐
相关产品推荐

