在 C++20 中,您可以通过几种不同的方式编写约束函数模板:
template <typename T>
concept Fooable = true;
template <typename T>
requires Fooable<T>
void do_something(T&); // (1)
template <typename T>
void do_something(T&) requires Fooable<T>; // (2)
Run Code Online (Sandbox Code Playgroud)
根据这个问题中接受的答案,这两种形式是等价的(这一直是我的理解)。
但是,我注意到 GCC 12.1 认为 (1) 和 (2) 是两个不同的函数,而不是 (2) 是重新声明:可以为两者提供定义,并且尝试调用do_something()是不明确的(示例)。
编辑:
(我依稀记得在 Concepts TS 时代,需求经过“规范化”来决定它们何时等效——我想在 C++20 中不再是这种情况了?)
我有一些像这样的功能
bool RegisterModel (std::shared_ptr<DerivedA> model) { }
bool RegisterModel (std::shared_ptr<DerivedB> model) { }
Run Code Online (Sandbox Code Playgroud)
我想利用 c++ 20 概念并像这样实现它:
bool RegisterModel (std::derived_from<BaseClass> auto model) { }
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为我正在传递共享指针。以某种方式可能需要一个共享指针来保存从BaseClass?派生的对象。
我对 C++20 概念仍然很陌生,我想知道为什么这不起作用。我想创建一个将数字连接为字符串的函数模板。所以我想尝试一些概念。我曾经std::convertible_to检查输入的数据类型(int在本例中)是否可以转换为std::string. 但我面临着一个我不明白的错误。
//building the concept
template <typename T>
concept ConvertibleToStdString = std::convertible_to<T,std::string>;
//using the concept
template <ConvertibleToStdString T>
std::string concatenate(T a, T b){
return std::to_string(a) + std::to_string(b);
}
int main(){
int x{623};
int y{73};
auto result = concatenate(x,y);
std::cout << result << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
错误:
main.cpp:21:34: error: use of function 'std::string concatenate(T, T) [with T = int; std::string = std::basic_string<char>]' with unsatisfied constraints
21 | auto result = concatenate(x,y);
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么 …
我对 TMP 还很陌生,所以如果这是一个措辞不好的问题,请原谅我。
我正在尝试创建一个非常通用的数学 Vector 类来存储任意数量的组件,但默认为 3 并使用 float 作为其基本表示形式。因此,如果您默认构造这些向量之一,它将保存(0.0f,0.0f,0.0f)
这些值本身存储在 a 中std::array,我想创建访问器函数以方便使用。我目前有这个:
std::array<Type,SIZE> e;
Type x() const {return e.at(0);};
Type y() const {return e.at(1);};
Type z() const {return e.at(2);};
Run Code Online (Sandbox Code Playgroud)
我现在想做的是为第四个组件设置一个,w但只有当该数组的大小 >= 4 时才启用它。所以像这样:
template<class Type, std::enable_if<.......>>
Type w() const {return e.at(3);};
Run Code Online (Sandbox Code Playgroud)
这只是我认为它应该是什么样子的一个模糊的想法。我知道concept存在,但我也在努力为这种情况写一个。
C++20 和 C++23 引入了迭代器对和范围的模板构造函数std::string_view。std::span有类似的构造函数。
template<class It, class End>
constexpr basic_string_view(It first, End last); // C++20
template<class R>
explicit constexpr basic_string_view(R&& r); // C++23
Run Code Online (Sandbox Code Playgroud)
该文档包含参数的要求。为什么这些要求没有定义为C++20 概念约束?这不会导致更好的错误消息吗?
有没有办法要求给定类型在其中定义类型别名?例如,我如何编写一个概念来检查这是否有效,其中该概念检查类型 T 是否具有类型别名Bar?
template <typename T>
concept HasBarType = ????;
template <HasBarType T>
void foo() {
[[maybe_unused]] T::Bar bar;
}
Run Code Online (Sandbox Code Playgroud) Scala traits Haskell类型类和C++ 0x Concepts之间有什么区别?
就像下面这个例子中Observer声明一个抽象成员一样,receiveUpdate Observer实际上是一个"匿名"类型或结构类型.
package observer
trait Subject {
type Observer = { def receiveUpdate(subject: Any) }
private var observers = List[Observer]()
def addObserver(observer:Observer) = observers ::= observer
def notifyObservers = observers foreach (_.receiveUpdate(this))
}
Run Code Online (Sandbox Code Playgroud) 我有以下代码实现以下类型特征:
std::vector std::vector整数它有效,但它非常冗长.
是否有更短/更好的方式来使用概念写这个?
我知道我可以从range-v3或其他类似的库中窃取概念,但我们假设我想自己实现它.
#include <iostream>
#include <string>
#include <type_traits>
#include <vector>
template <class T>
struct is_vector {
static constexpr bool value = false;
};
template <class T, class A>
struct is_vector<std::vector<T, A> > {
static constexpr bool value = true;
};
template <class T>
struct is_vector_of_int {
static constexpr bool value = false;
};
template <class A>
struct is_vector_of_int<std::vector<int, A> > {
static constexpr bool value = true;
};
// TODO add _v bool …Run Code Online (Sandbox Code Playgroud) 此代码段中显示了一个示例,该示例说明了在没有概念的情况下如何重载模板类的模板成员函数。
现在粗略尝试使用概念编写类似的东西:
template <typename T>
struct Foo{
Foo(T elem): elem_(elem) {}
template <typename U = T> requires Integral<U>
int get() {
return -1;
}
template <typename U = T> requires Bool<U>
int get() {
return 0;
}
T elem_;
};
Run Code Online (Sandbox Code Playgroud)
有两种方法可以组织这种情况:
1.将声明和定义保持在一起:这可以按预期工作。代码段
2。声明和定义分开:无法编译(代码段)
鉴于以上所述,我有两个问题:
1. template <typename T> template <typename U=T> member_fn...由于SFINAE,最初需要该原因。有没有办法用Concepts来避免这种情况来进一步简化代码?
2.如何正确区分声明和定义?