我无法理解requires关键字如何在嵌套模板中工作。
下面的代码可以在最新版本的 MSVC 和 gcc 上编译(分别使用/std:c++latest和)。-std=c++2a
requires在这样的场景中是否会被简单地丢弃?我不应该这样使用它吗?
#include <type_traits>
template <
template < typename >
requires (false) // Should not this stop compilation?
typename Wrapper >
using Test = Wrapper < int >;
template < typename >
struct S
{
};
int main() {
Test < S > var;
return 0;
}
Run Code Online (Sandbox Code Playgroud) 我有一个简单的模板类A。如果满足某些要求,我想启用一项功能。
requires子句我尝试的第一个解决方案如下:
template <class T>
class A
{
public:
void a(void) requires (same_as<T, int>)
{
std::cout << "a" << std::endl;
};
};
Run Code Online (Sandbox Code Playgroud)
这效果非常好。我可以打电话,A<int>().a()但不能A<char>().a();。此外,IntelliSense 可以正确识别 Visual Studio 中的使用错误。
我尝试将函数定义移到类之外,但在 Visual Studio 中出现 C2511 编译器错误。在海湾合作委员会,它工作得很好。
template <class T>
class A
{
public:
void a(void) requires (same_as<T, int>);
};
template <class T>
void A<T>::a(void)
requires (same_as<T, int>)
{
std::cout << "a" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
您认为我的代码不正确还是 Visual Studio 编译器错误/功能不完整?
static_assert该解决方案在某些情况下有效,但如果您尝试显式模板实例化(例如template …
在以下示例中,第二个f函数重载的需要表达式的类型为std::integral_constant<bool,true>,它可以隐式转换为bool:
#include <type_traits>
struct S {
static constexpr bool valid = true;
};
template<typename T>
int f() { return 1; }
template<typename T>
int f() requires( std::bool_constant< T::valid >() ) { return 2; }
int main() {
return f<S>();
}
Run Code Online (Sandbox Code Playgroud)
可以观察到,GCC 由于类型不精确而拒绝该程序bool,但 Clang 接受,但选择了另一个重载int f() { return 1; }。演示: https: //gcc.godbolt.org/z/nf65zrxoK
这里哪个编译器是正确的?
我尝试让成员函数要求静态 constexpr 布尔成员为 true。这对于 DRY 一个相当复杂的需求非常有帮助。我不知道编译器不允许我这样做的原因。
要求稍微不那么复杂的最小示例:
template <typename T>
struct Foo
{
static constexpr bool isInt = std::integral<T>;
void bar() requires (isInt);
void goo() requires std::integral<T>;
};
template <typename T>
void Foo<T>::bar() requires (Foo<T>::isInt) // error: out-of-line definition of 'bar' does not match any declaration in 'Foo<T>' x86-64 clang 14.0.0 #1
{
// ...
}
template <typename T>
void Foo<T>::goo() requires std::integral<T> // ok
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
这是因为isInt是在同一个类中声明的吗?或者我有某种语法错误?
这给出了一个错误:
template <class T, T A, T B>
requires A > B // <-- error
class X{};
Run Code Online (Sandbox Code Playgroud)
错误:requires 子句中的该表达式周围需要括号
Run Code Online (Sandbox Code Playgroud)requires A < B ~~^~~ ( )
几乎所有操作员都会出现此错误 ( requires A > B, requires A == B, requires A & B, requires !A)
然而&&并且||似乎有效:
template <class T, T A, T B>
requires A && B // <-- ok
class X{};
Run Code Online (Sandbox Code Playgroud)
在 godbolt 上使用 gcc trunk 和 clang trunk(2020 年 5 月)进行睾丸测试。两个编译器给出相同的结果。