概念没有制定C++ 0x标准,但Boost仍然提供了Boost概念检查库(BCCL).我想BCCL并未涵盖C++ 0x标准的所有内容.BCCL和提议的C++ 0x解决方案有什么区别?
考虑class A满足两个概念ConceptA和ConceptB.让一个函数foo重载两个概念:
void foo(ConceptA& arg);
void foo(ConceptB& arg);
A a;
fun(concept_cast<ConceptA>(a));
Run Code Online (Sandbox Code Playgroud)
注意:此示例使用作为N3701,§5的一部分提出的"Terse Notation"语法
是否存在concept_cast允许用户选择重载的东西?
例如:可以说,
ConceptA说T有权有一个成员函数bar()
ConceptB说T有权有一个成员函数baz()
,并class A同时具有bar()和baz()成员函数
它显然是模棱两可的,但有没有办法明确选择我们static_cast正常的重载?
更新:已接受的答案超过2年.c ++ 17中的任何更新?
C++20 引入了概念,这是一种对模板函数或类可以采用的类型施加约束的智能方法。
虽然迭代器类别和属性保持不变,但改变的是执行它们的方式:C++17 之前使用标记,C++20 以来使用概念。例如,您可以使用 std::forward_iterator 概念来标记迭代器,而不是使用 std::forward_iterator_tag 标签。
同样的事情也适用于所有迭代器属性。例如,前向迭代器必须是 std::incrementable。这种新机制有助于获得更好的迭代器定义,并使编译器中的错误更具可读性。
这段文字摘自这篇文章: https ://www.internalpointers.com/post/writing-custom-iterators-modern-cpp
但作者并没有升级如何用概念在C++20上制作自定义迭代器的内容,仍然是<= C++17标签版本。
有人可以举例说明如何使用概念功能在 C++20 版本中为自定义容器编写自定义迭代器吗?
为什么 C++ 20 中使用 require 表达式的“Oneable”概念的某些实现无法在某些编译器上编译?
// `Oneable` implemented using `requires` with a simple assignment expression
// clang, gcc, and msvc all compile
template <class T>
concept Oneable = requires(T n) { n = 1; };
static_assert(Oneable<int>);
static_assert(!Oneable<int*>);
Run Code Online (Sandbox Code Playgroud)
// `Oneable` implemented using `requires` with an assignment statement inside
// the body of a lambda expression
// clang and msvc compile
// gcc gives a compiler error on instantiating Oneable<T*>
template <class T>
concept Oneable = requires { []() { T …Run Code Online (Sandbox Code Playgroud) 我有一个 CRTP 课程
template <typename T>
class Wrapper
{
// ...
};
Run Code Online (Sandbox Code Playgroud)
旨在导出为
class Type : Wrapper<Type>
{
// ...
};
Run Code Online (Sandbox Code Playgroud)
我想通过对模板参数施加约束来强制执行T。有一个friend技巧可以做到这一点,但我认为在概念时代应该有更好的方法。我的第一次尝试是
#include <concepts>
template <typename T>
requires std::derived_from<T, Wrapper<T>>
class Wrapper
{
// ...
};
Run Code Online (Sandbox Code Playgroud)
但这不起作用,因为我指的是Wrapper在声明之前。我发现了一些不完全令人满意的解决方法。我可以将约束添加到构造函数
Wrapper() requires std::derived_from<T, Wrapper<T>>;
Run Code Online (Sandbox Code Playgroud)
但是如果我有更多的构造函数也必须受到约束,这就不方便了。我可以用析构函数来做
~Wrapper() requires std::derived_from<T, Wrapper<T>> = default;
Run Code Online (Sandbox Code Playgroud)
但是声明析构函数只是为了穿上它感觉有点傻requires。
我想知道是否有更好,更惯用的方法来做到这一点。特别是,虽然这些方法似乎有效(在 gcc 10 上测试过),但一件令人不满意的事情是,如果我Type从派生Wrapper<OtherType>,那么只有在我实例化 时才会引发错误Type。是否有可能在定义点出现错误Type?
在 GCC C++20 概念库中,它有
template<typename _Derived, typename _Base>
concept derived_from = __is_base_of(_Base, _Derived)
&& is_convertible_v<const volatile _Derived*, const volatile _Base*>;
Run Code Online (Sandbox Code Playgroud)
__is_base_of(_Base, _Derived)不够?const volatile测试中需要用到什么?从 C++20 开始,我们可以在auto关键字前面加上概念的名称来限制可能的类型。特别是这种组合在类转换中是可能的operator auto,例如
template <typename T> concept x = true;
struct S
{
operator x auto() { return 2; }
operator auto() { return 1; }
};
int main() { return S{}.operator x auto(); }
Run Code Online (Sandbox Code Playgroud)
但是 Clang 是唯一接受整个程序的编译器,但是main()返回1(而不是2我预期的那样),演示:https : //gcc.godbolt.org/z/b16jYGa81
GCC 接受结构体定义,但拒绝编译S{}.operator x auto().
即使struct S出现错误,MSVC 也拒绝接受:
error C2535: 'S::operator auto(void)': member function already defined or declared
Run Code Online (Sandbox Code Playgroud)
只是想知道,哪个编译器就在这里(如果有的话)?
最新的标准草案N4910在 [temp.over.link] 中有关于功能等效性的示例:
template<int I> concept C = true;
template<typename T> struct A {
void f() requires C<42>; // #1
void f() requires true; // OK, different functions
};
Run Code Online (Sandbox Code Playgroud)
我的理解是,这没问题,因为C<42>和true是未评估的操作数。因此,根据[temp.over.link]/5,在考虑约束是否在功能上等价时,不是表达式的结果,而是对哪个实体执行什么操作以及以什么顺序执行,才是决定约束功能等价的。
但是,如果约束在功能上等效,那么由于它们不等效,根据[temp.over.link]/7,程序将格式错误,无需诊断,因为两次声明同一成员将使程序格式错误。
另一方面
template<typename>
requires C<42>
void g() {};
template<typename>
requires true
void g() {};
Run Code Online (Sandbox Code Playgroud)
似乎格式不正确,不需要诊断,因为[temp.over.link]/6表示如果模板头接受并满足相同的模板参数,则它们在功能上是等效的。
我是否误解了示例并引用了标准措辞,或者真的有这样的差异吗?如果是这样,为什么?
假设我有两个课程:
\ntemplate <typename X, typename Y>\nclass Functor {};\n\ntemplate <typename Start, typename End, typename ...Functors>\nclass Template {};\nRun Code Online (Sandbox Code Playgroud)\nTemplate有以下限制:
全部Functors必须是类型Functor
所有内容都Functor必须按链式顺序排列,这样
Functor必须Start作为其第一个参数Functor必须End作为第二个参数Functor\ 的第一个参数是前面它的第二个参数Functor例如Functor<A,B>, Functor<B, C>, Functor<C, D>, ...等等。
从...开始:char
结尾为: …
我查看了 clang-format 样式选项https://clang.llvm.org/docs/ClangFormatStyleOptions.html但没有看到任何对 c++ 概念和需要子句的引用。通常我可以配置 clang-format 来做我想做的事,但我不知道如何让它很好地处理我的概念和需要条款:
template <typename F, typename P, typename T>
concept Accumulate_Fn = Parser<P>&& std::invocable<F, T, parser_t<P>>&&
std::same_as<T, std::invoke_result_t<F, T, parser_t<P>>>;
Run Code Online (Sandbox Code Playgroud)
但是我想将每个约束放在自己的行上(就像它处理太长的函数参数一样),以便结果如下所示:
template <typename F, typename P, typename T>
concept Accumulate_Fn = Parser<P> &&
std::invocable<F, T, parser_t<P>> &&
std::same_as<T, std::invoke_result_t<F, T, parser_t<P>>>;
Run Code Online (Sandbox Code Playgroud)
template <Parser P1, Parser P2, typename T, Accumulate_Fn<P1, parser_t<P1>> F>
requires std::same_as<T, parser_t<P1>> constexpr Parser auto
separated_by(P1&& p1, P2&& p2, T&& init, F&& f)
Run Code Online (Sandbox Code Playgroud)
但我想要更接近的东西: …