想象一下我有一个可调用的模板参数“Fn fn”。现在我想检查它的返回类型是否是有符号标量。我如何使用 C++20 概念做到这一点?
我需要要求某种类型 A 存在一个函数 f(A, A::B)。
我正在通过使用 A 和 A::B 的实例调用 f 来测试这一点。是否有一种不那么招摇的方法来测试依赖类型的实例而不需要默认可构造?
template <class Container>
concept CanPutData = requires (Container a)
{
//put(typename Container::data_type{}, a); // overconstrained
put(*reinterpret_cast<typename Container::data_type*>(0), a); // oof
};
void test(CanPutData auto container) {}
template<class Container>
void put(typename Container::data_type const& data, Container& into) {}
template<class Data>
struct data_container { using data_type = Data; };
struct not_default_constructible_data { int& v; };
int main()
{
test(data_container<not_default_constructible_data>{});
return 0;
}
Run Code Online (Sandbox Code Playgroud) 这个相当简单:根据cppreference 文章,概念可以毫无问题地重新声明:
所以我想好吧,很酷,我不必担心重新声明我创建“可打印枚举”的概念;我可以在日志记录标头和常见类型标头中声明该概念,因此我只需包含所需的内容:
// common types header
#include <enum_traits.hpp>
template<typename E>
concept PrintableEnum = requires(E& e) { {enum_traits<E>::toString(e)} -> std::same_as<const char*>; };
template<PrintableEnum T>
std::ostream& operator<<(std::ostream& os, const T& o)
{
os << enum_traits<T>::toString(o);
return os;
}
// logging header
template<typename T>
concept PrintableEnum = requires(T& e) { {enum_traits<T>::toString(e)} -> std::same_as<const char*>; };
template<PrintableEnum T>
plog::Record& operator<<(plog::Record& rec, const T& o)
{
rec << enum_traits<T>::toString(o);
return rec;
}
Run Code Online (Sandbox Code Playgroud)
(忽略 ostream 过载可能暂时覆盖 plog 记录过载;这可能是我解决该问题的方法,但我首先对此感到好奇。)
因此,当我尝试编译此文件时,MSVC 会为包含两个标头的每个文件抛出一个合适的情况(它指向哪一个,因为错误根据包含顺序而变化):
[build] commontypes.hpp(25): error …Run Code Online (Sandbox Code Playgroud) 我有一个类模板,我想编写如下:
template </*what to put here?*/ T>
Class Bar {};
Run Code Online (Sandbox Code Playgroud)
我想强制 T 只能是作用域枚举中的值。我使用了此处is_scoped_enum提供的类型检查,但是我能想到的最好的办法就是更改为如下所示:Bar
template <typename T>
concept ScopeEnum = is_scoped_enum<T>::value;
template<ScopeEnum SE, SE se>
class Bar {};
Run Code Online (Sandbox Code Playgroud)
我怎样才能实现它并Bar保持预期的效果?
我正在努力满足我的班级的 C++20 概念。
struct C1
{
int* begin();
int* end();
};
static_assert(std::ranges::range<C1>); // Compiles fine
struct C2 {};
namespace std::ranges // (A)
{
auto begin(C2&);
auto end(C2&);
}
static_assert(std::ranges::range<C2>); // Fails to compile
Run Code Online (Sandbox Code Playgroud)
该std::ranges::range<>概念定义如下:
template <class _Rng>
concept range = requires(_Rng& __r) {
std::ranges::begin(__r);
std::ranges::end(__r);
};
Run Code Online (Sandbox Code Playgroud)
从字面意思上看,它指示我声明上面的函数 (A)。但这些都没有帮助。另一方面,像在类中一样定义两个成员函数C1 确实有效。我的问题是,我只是看不到概念所强加的要求与有助于 class 的解决方案之间的语义联系C1。它告诉我做一件事,而实际上我需要做另一件事。
请对此提供一些解释。
背景:在我的生产代码中,我的类确实定义了一个begin()和end()函数,每个函数返回一个迭代器。但这个range概念并不满足这些定义,也未能告诉我原因。
请参阅编译器资源管理器上的完整示例
我正在尝试 C++20 功能,并且我想用来concept限制模板仅传递具有名为 的成员List且其类型应该为 的类std::vector<int>。这是前言。
要在不使用 的情况下执行此操作concept,我将编写以下代码:
class RandomClass
{
public:
std::vector<int> List;
};
typename std::enable_if<std::is_same<decltype(T::List), std::vector<int>>::value>::type
func(T& arg)
{
...
}
int main()
{
auto randomObj= RandomClass();
func(randomObj);
}
Run Code Online (Sandbox Code Playgroud)
我要求 New Bing 使用concept重写它,它给出了以下内容:
template<class T>
concept HasList = requires(T t) {
{ t.List } -> std::same_as<std::vector<int>>;
};
template<class T> requires HasList<T>
void func(T& arg)
Run Code Online (Sandbox Code Playgroud)
但是这段代码无法编译,编译器给出了'func': no matching overloaded function found.
然后我搜索std::same_as用法并尝试了这个:
template<class T>
concept HasList …Run Code Online (Sandbox Code Playgroud) 我正在使用cppreference.com - Constraints and Concepts (Since C++20)中的示例学习 C++ 概念,我将在此处将其重现为:
template <typename T>
requires std::integral<T> || std::floating_point<T>
constexpr double average(std::vector<T> const &vec) {
const double sum = std::accumulate(vec.begin(), vec.end(), 0.0);
return sum / vec.size();
}
int main()
{
std::vector sVec { 1, 2, 3, 4, 5};
assert(average(sVec) == 3);
}
Run Code Online (Sandbox Code Playgroud)
我添加了 std::array 的情况:
template <typename T, int size> // add size
requires std::integral<T> || std::floating_point<T>
constexpr double average(const std::array<T, size> &arr) { // use std::array<T, size> &arr) instead
const double …Run Code Online (Sandbox Code Playgroud)