我很好奇这是否是 C++23 中定义的行为,即具有接受
template
的 template
-typename
,并且能够插入接受 template
的 concept
(其中 accepts
typename
)?
这是一个例子:
#include <iostream>
#include <type_traits>
template<typename T>
concept MyConcept = std::is_integral_v<T> || std::is_floating_point_v<T>;
template<template<typename> typename TT>
struct A {
template<typename T>
using Type = TT<T>;
};
template<MyConcept T>
struct B {
T bb;
};
int main(int argc, char** args)
{
auto a = A<B>{}; // Ok? Compiles with gcc 13.2.1 and clang-16.0.6
auto b = decltype(a)::Type<int>{};
return 0;
}
相反的情况似乎也可以编译,这让我更加怀疑
template<template<MyConcept> typename TT>
struct A {
template<typename T>
using Type = TT<T>;
};
template<typename T>
struct B {
T bb;
};
int main(int argc, char** args)
{
auto a = A<B>{}; // Ok? Compiles with gcc 13.2.1 and clang-16.0.6
auto b = decltype(a)::Type<int>{};
return 0;
}
这里,在一定的读数下,我们应该接受一个
template
到template
-template
iff,模板接受一个MyConcept
,但是B
的template
是不受约束的?
这些示例中的任何一个都是未定义的行为,还是它们的行为符合标准定义?
谢谢!
根据公开可用的 C++23 标准工作草案,这似乎是“已定义”行为并且是正确的。 § 13.4.4 第 3 段下的示例 4 似乎准确地表明了这一点,根据标准:
template<typename T> concept C = requires (T t) { t.f(); };
template<typename T> concept D = C<T> && requires (T t) { t.g(); };
template<template<C> class P> struct S { };
template<C> struct X { };
template<D> struct Y { };
template<typename T> struct Z { };
S<X> s1; // OK, X and P have equivalent constraints
S<Y> s2; // error: P is not at least as specialized as Y
S<Z> s3; // OK, P is at least as specialized as Z
示例 2 中的这一点看起来也很相关:
template<auto n> class D { /* ... */ };
//...
template<template<int> class R> class Z { /* ... */ };
//...
Z<D> zd; // OK