MyConcept假设我有一个描述通用算法要求的概念algo。在下面的示例代码中,唯一的要求是一个自由函数my_free_function,它接受一个MyConcept类型并返回相同的类型,并且存在三种满足要求的类型。
template<class T>
concept MyConcept = requires (T a) {
{ my_free_function(a) } -> std::same_as<T>;
};
template<MyConcept T>
auto algo(T& a) {
return my_free_function(a);
}
namespace baz {
struct bar {};
bar my_free_function(bar) { return bar{}; }
}; // baz
unsigned long my_free_function(unsigned long) { return 42; }
namespace caz {
using NativeU64 = unsigned long;
NativeU64 my_free_function(NativeU64) { return NativeU64{42ul}; }
}; // caz
Run Code Online (Sandbox Code Playgroud)
我的挑战是,为了获得以下调用来编译 NativeU64 和 unsigned long,我必须在概念和算法之前定义 my_free_function 。这是唯一的选择吗?我当前的代码组织和依赖结构依赖于能够在头文件中定义概念和算法,编译器在看到满足要求的定义之前会使用这些概念和算法。
auto …Run Code Online (Sandbox Code Playgroud) 如何编写一个要求类具有noexcept构造函数的概念?例如,以下内容static_assert在 Clang 15.0.7 中是正确的,尽管我觉得不应该。
class Ragdoll {
int age_ = -1;
public:
Ragdoll(int age) /* noexcept */ : age_(age) {}
int meow() const;
int lose_hair();
};
template<typename Cat>
concept cat = requires(Cat cat) {
noexcept(Cat{42});
{ cat.meow() } -> std::same_as<int>;
};
static_assert(cat<Ragdoll>);
Run Code Online (Sandbox Code Playgroud)
noexcept那么这个表达式在概念中到底在做什么呢?(也请随意链接任何好的概念教程)
我有一个 C++ 宏,我想用它来调用一个重载的函数模板。我希望这些函数模板之一仅接受浮点值,而另一个函数模板将接受其他所有内容。
以下是我使用 C++ 20 在https://cpp.sh/中运行的代码:
#include <iostream>
#include <string>
#include <vector>
#include <type_traits>
#include <concepts>
template< typename T>
concept NotFloatingPoint = requires
{
!std::is_same_v<T, double> || !std::is_same_v<T, float>;
};
template< NotFloatingPoint T, NotFloatingPoint U, bool isDistanceType_ = false >
void ProcConstantConfigForce( T& value_ )
{
std::cout << "Inside ProcConstantConfigForce()\n";
std::cout << value_;
}
template< typename T>
concept FloatingPoint = requires
{
std::is_same_v<T, double> || std::is_same_v<T, float>;
};
template< FloatingPoint T, FloatingPoint U, bool isDistanceType_ = false > …Run Code Online (Sandbox Code Playgroud) 我正在逐步学习模板,我认为这是我当前项目需要做的最后一件事:
template < typename Object, bool Shared>
class Foo {
private:
struct SubFoo {
//if Shared == true -> FooShared foo;
//if Shared == false -> FooBasic foo;
??? foo;
Object data;
};
};
Run Code Online (Sandbox Code Playgroud)
我知道MagicType foo;这样做不会那么容易,不用担心修改代码.我没有C++限制(g ++ 6.2,我想知道如何获得g ++ 7)所以即使是概念也是受欢迎的.
编译器是否保证评估环境constexpr中"tautologies"(例如始终true或false分别)的布尔表达式constexpr?
例如,在以下代码片段(在标有 的行(1))中,我在constexpr环境中调用了一个函数,我打算在non-constexpr传递函数时导致编译时错误。至少我使用的编译器 ( g++-10.0) 是这样做的,即使它也可以意识到表达式总是true不计算它。我问这个问题的原因是 - 据我所知 - 在非 constepxr 上下文中,像这样的表达式i >= std::numeric_limits<int>::min()被优化true为int i.
#include <limits>
constexpr int example_function() { return 1;}
constexpr bool compileTimeErrorDesired = example_function() || true; // (1)
Run Code Online (Sandbox Code Playgroud)
如果(1) 保证in 的行为,则可以在 aconcept中使用它,以执行不同的代码,具体取决于是否可以在编译时评估作为模板参数提供的函数。我实现了一个非常短的 ( 7 lines-of-code) 示例,它在编译器资源管理器中完全做到了这一点。
如果使用非 constexpr 函数调用,行 (1) …
#include <type_traits>
struct A
{
~A() {}
};
int main()
{
static_assert(std::is_trivial_v<A>); // error
}
Run Code Online (Sandbox Code Playgroud)
它似乎很明显,std::is_trivial_v<A>将是false如果A有一个析构函数。
但是,从 的cppref 页面中std::is_trivial,没有什么要求A一定不能有析构函数。
什么时候可以 T 有析构函数 std::is_trivial_v<T> ?
我正在尝试实现以下概念
template<typename T>
concept GameLogic = requires(T a) {
typename T::StateType;
typename T::EventType;
{ a.initialState()->T::StateType }; // <-- relevant bit
};
Run Code Online (Sandbox Code Playgroud)
我想强制initialState()返回类型是同一类的嵌套类型。
概念定义不会引发错误(gcc 9.2),但以下实现GameLogic无法满足要求:
class SimpleGameLogic {
public:
using StateType = SimpleState;
using EventType = SimpleEvent;
StateType initialState() {
return _initialState;
}
private:
StateType _initialState;
};
Run Code Online (Sandbox Code Playgroud)
我已经尝试了上述语法的一些变体,但找不到正确的语法...或者这可能尚未实现?我究竟做错了什么?
考虑一个概念is_red,检查给定类型是否具有color设置为 的静态 cx 成员/*undefined*/::red,其中枚举中的`/ undefined /;
template <typename T>
concept is_red = requires(T) {
{ T::color == decltype(T::color)::red };
};
Run Code Online (Sandbox Code Playgroud)
这显然是错误的,因为它只检查合成是否定义良好。
因此,这不会按预期工作:
namespace apple {
enum colors{red, green, yellow };
struct granny_smith{
constexpr static auto color = colors::green;
};
}
static_assert(is_red<apple::granny_smith>); // should fail, but it does not using the previous concept implementation
Run Code Online (Sandbox Code Playgroud)
请参阅此处有关 godbolt 的实例。
这是我目前评估概念价值的方式:
template <bool condition>
using if_t = std::conditional_t<condition, std::true_type, std::false_type>;
template <typename T>
concept is_red …Run Code Online (Sandbox Code Playgroud) 我是模板编程的新手,并且偶然发现了这个习惯用法。例如,类似:
class FooBase {
public:
virtual void do_something() = 0;
};
template <class Foo> // Foo is derived from FooBase
void g(Foo& foo) {
static_assert(std::is_base_of<FooBase, Foo>::value);
// ...
foo.do_something();
// ...
}
Run Code Online (Sandbox Code Playgroud)
在我看来,这种模式很有用,因为:
requires子句(如果可用的话)相比,指定属性、参数和返回类型很容易。FooBase标头即可清楚定义新 Foo 类的要求。FooBase类中。但是我担心使用的性能影响virtual函数对性能的影响。我的理解是运行时没有成本,因为该函数是从派生类调用的;但链接器将无法内联该函数。
另一个缺点是不允许虚拟模板功能。
最后,我担心这可能是一种代码味道,因为它使用运行时多态性功能来执行静态检查。C++20 概念可能是执行此操作的“正确”方法,但由于上述三个原因,它们似乎不太方便。
c++ ×10
c++-concepts ×10
c++20 ×7
templates ×3
type-traits ×2
constexpr ×1
destructor ×1
iterator ×1
noexcept ×1
polymorphism ×1
standards ×1