默认模板参数在C++中何时被替换?

8yoxcaq7  于 2023-02-17  发布在  其他
关注(0)|答案(1)|浏览(96)

由于C中的每个lambda函数都有自己的类型,并且lambda函数的类型可以用作模板参数的默认值,因此了解模板中的类型何时被替换是很有趣的。考虑一个C20程序示例:

#include <concepts>

template<typename T = decltype([]{})>
using X = T;

template<typename T = X<>>
auto foo() { return T{}; }

int main() {
    using T1 = decltype(foo());
    using T2 = decltype(foo());
    static_assert(!std::same_as<T1, T2>);
}

这里,类型别名X定义中的模板参数的默认类型是lambda函数decltype([]{})的类型,并且模板函数调用foo()返回该类型的值。
如果每次foo()出现在程序中时都会替换新的lambda类型,那么T1T2类型必须是不同的,因为程序在static_assert中进行验证。
在Clang和MSVC中,类型T1T2是相同的,这意味着默认类型的替换不是每次都发生(而是在模板声明期间发生一次)。https://gcc.godbolt.org/z/dzYjf9r3q
根据标准,这里有哪个编译器?

pepwfjgg

pepwfjgg1#

lambda只是函子结构体,这个语法上的糖在最上面就被解析了,甚至在优化过程发生之前。
我已经修改了assert以使代码可编译。如果将此代码应用于cppinsights.io,您可以看到类型解析为单个struct类型。

#include <concepts>

template<typename T = decltype([]{})>
using X = T;

template<typename T = __lambda_4_32>
auto foo()
{
  return T{};
}

#ifdef INSIGHTS_USE_TEMPLATE
template<>
__lambda_4_32 foo<__lambda_4_32>()
{
  return __lambda_4_32{};
}
#endif

int main()
{
  using T1 = __lambda_4_32;
  using T2 = __lambda_4_32;
  /* PASSED: static_assert(std::same_as<__lambda_4_32, __lambda_4_32>); */
  return 0;
}

相关问题