在这个 SO 答案和这个提案中,我们可以看到 的实现(为了方便起见,在下面包含)std::is_specialization_of,它可以检测类型是否是给定模板的特化。
template< class T, template<class...> class Primary >\nstruct is_specialization_of : std::false_type {};\n\ntemplate< template<class...> class Primary, class... Args >\nstruct is_specialization_of< Primary<Args...>, Primary> : std::true_type {};\nRun Code Online (Sandbox Code Playgroud)\n该提案明确指出此类型特征不受继承影响:
\n\n\n所提出的特征仅考虑专业化。由于特化与继承无关,因此当任何模板参数恰好通过继承定义时,trait\xe2\x80\x99s 结果不受影响。
\n
template< class > struct B { };\ntemplate< class T > struct D : B<T> { };\n\nstatic_assert( is_specialization_of_v< B<int>, B> );\nstatic_assert( is_specialization_of_v< D<int>, D> );\n\nstatic_assert( not is_specialization_of_v< B<int>, D> );\nstatic_assert( not is_specialization_of_v< D<int>, B> );\nRun Code Online (Sandbox Code Playgroud)\n有没有一种方法可以实现确实考虑继承的东西,其行为类似于 …
我想创建一个通用print(x)函数,它对于不同类型有不同的行为。
到目前为止,我所拥有的适用于所有容器类型,包括我自己编写的容器类型。然而,要么调用了“错误”的函数,要么由于不明确而无法编译。
这是我的代码:
#include <iostream>
#include <concepts>
class Container
{
int x, y, z;
public:
Container(int a, int b, int c) : x(a), y(b), z(c) {}
Container() : x(0), y(0), z(0) {}
std::size_t size() const { return 3; }
const int& operator[] (std::size_t index) const { if(index == 0) return x; else if(index == 1) return y; else return z; }
int& operator[] (std::size_t index) { if(index == 0) return x; else if(index == 1) return y; else …Run Code Online (Sandbox Code Playgroud) 有没有办法使用 c++20s 概念来检查值是否满足某些要求?
假设我正在编写某种使用分页的容器,并且我想让页面大小成为模板参数。
template<typename Type, std::size_t PageSize>
class container;
Run Code Online (Sandbox Code Playgroud)
我可以使用带有 constexpr 函数的静态断言来检查PageSize类体内是否为 2 的幂。
但有没有办法用新观念来约束呢PageSize?
我正在尝试使用 C++ 概念来编写一个类型特征,该特征将根据其模板参数是否为基本类型而生成不同的类型:
template<typename T>
concept fundamental = std::is_fundamental_v<T>;
template<typename T>
concept non_fundamental = !std::is_fundamental_v<T>;
Run Code Online (Sandbox Code Playgroud)
以下代码按预期工作:
void Print(fundamental auto value)
{
std::cout << "fundamental\n";
}
void Print(non_fundamental auto value)
{
std::cout << "non fundamental\n";
}
int main()
{
Print(1); // prints "fundamental"
Print(std::string("str")); // prints "non fundamental"
}
Run Code Online (Sandbox Code Playgroud)
对类型特征应用相同的想法是行不通的。
template<fundamental T>
struct SomeTypeTrait
{
using type = T;
};
template<non_fundamental T>
struct SomeTypeTrait
{
using type = std::shared_ptr<T>;
};
using ExpectedToBeDouble = SomeTypeTrait<double>::type;
using ExpectedToBeSharedPtrOfString = SomeTypeTrait<std::string>::type; // fails to …Run Code Online (Sandbox Code Playgroud) 我有一个Optional_monadic 类,它是从 std::Optional 类继承的
template <class T>
class monadic_optional : public std::optional<T>
{
public:
using std::optional<T>::optional;
monadic_optional(T value) : std::optional<T>(value) {}
}
Run Code Online (Sandbox Code Playgroud)
在这堂课中我描述了该方法
template <class Return>
nonstd::monadic_optional<Return> and_then(std::function<nonstd::monadic_optional<Return>(T)> func)
{
if (this->has_value())
return func(this->value());
else
return std::nullopt;
}
Run Code Online (Sandbox Code Playgroud)
我想使用概念将模板传递给检查它是否是函数的方法。我如何使用概念来实现这一点?
template <class T>
concept convertible_to_func = std::convertible_to <T, std::function<nonstd::monadic_optional<Return>(T)>>
requires
{
};
nonstd::monadic_optional<T> and_then(T func)
{
if (this->has_value())
return func(this->value());
else
return std::nullopt;
}
Run Code Online (Sandbox Code Playgroud)
它应该看起来像这样,但它无法编译。
让我们考虑以下用于阶乘函数的编译时计算的代码:
#include <concepts>
template <std::integral auto num>
struct factorial {
constexpr static auto val{num * factorial<num - 1>::val};
};
// Note: This only specializes the class for (int)0
template <>
struct factorial<0> {
constexpr static auto val{1};
};
// ...
factorial<4>::val; // Ok: 24
factorial<4u>::val; // error: template instantiation depth exceeds maximum of 900
// This makes sense: There's no factorial<0u> specialization.
Run Code Online (Sandbox Code Playgroud)
factorial<0>有没有办法为所有整型(即满足 的所有类型)引入专门化std::integral?
当然,我想避免实际写出专业化factorial<0u>,factorial<0l>等等。
请参阅下面的代码(也可在此处https://www.godbolt.org/z/hvnvEv1ar)。rng如果我取消注释或的约束,代码将无法编译pair。我觉得我错过了一些微不足道的东西,但我无法弄清楚为什么不满足约束。
#include <vector>
#include <ranges>
#include <utility>
template <typename T>
struct is_reference_wrapper : std::false_type {};
template <typename T>
struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type {};
template <typename T>
inline constexpr bool is_reference_wrapper_v = is_reference_wrapper<T>::value;
template <typename T>
concept ReferenceWrapper = is_reference_wrapper_v<T>;
template <typename T>
concept ReferenceWrapperPair = requires(const T& t) {
{ t.first } -> ReferenceWrapper;
{ t.second } -> ReferenceWrapper;
};
template <typename T>
concept ReferenceWrapperPairRange =
std::ranges::range<T> && ReferenceWrapperPair<std::ranges::range_value_t<T>>;
int main()
{
std::vector<std::pair<int, int>> …Run Code Online (Sandbox Code Playgroud) 我不明白搬家的要求从何而来。forward_range我在and ...\n基本示例中找不到它sized_sentinel:
\n #include <ranges>\n #include <string>\n #include <iostream>\n \n class vrange: public std::ranges::view_interface<vrange>\n {\n public:\n vrange(std::string &d): data(d){;};\n \n vrange(const vrange &&) = delete;\n \n auto begin() const noexcept { return data.begin(); };\n auto end() const noexcept { return data.end(); };\n \n private:\n std::string data;\n };\n \n int main(){\n std::string h("Hello world");\n vrange r(h);\n \n std::cout << r.size() << std::endl;\n for (const auto &i: r){\n std::cout << i;\n }\n std::cout << std::endl;\n \n \n …Run Code Online (Sandbox Code Playgroud) 假设我们有一个简单的概念,例如:
template <typename T>
concept MyConcept = requires {
T::value == 42;
};
Run Code Online (Sandbox Code Playgroud)
根据我的理解,这个概念是说,如果代码T::value == 42对于类型 T 有效,我就会通过。所以value必须是静态成员,对吗?
我有一个struct
struct Test { int value = 0; }
Run Code Online (Sandbox Code Playgroud)
和下一个模板函数
template <MyConcept T>
void call() { /*...*/ }
Run Code Online (Sandbox Code Playgroud)
当我尝试这样做时:
int main()
{
call<Test>();
}
Run Code Online (Sandbox Code Playgroud)
有用!
问题是:它为什么有效? Test::value == 42不是该类型的有效代码Test。
我找到了一种修复它的方法,例如:
template <typename T>
concept MyConcept = requires {
*(&T::value) == 42;
};
Run Code Online (Sandbox Code Playgroud)
它按预期“工作”:
<source>:6:20: note: the required expression '((* & T::value) == 42)' is …Run Code Online (Sandbox Code Playgroud) 概念很棒,不要误会我的意思,但是为什么我们需要另一个关键字呢?
考虑以下示例:
#include <type_traits>
template <typename T>
concept UnsignedConst = std::is_integral_v<T> && std::is_const_v<T>;
template <UnsignedConst T>
void foo(T bar);
Run Code Online (Sandbox Code Playgroud)
我们也可以使用以下(我认为更直接的)语法:
/* ... */
template <typename T>
constexpr bool UnsignedConst = std::is_integral_v<T> && std::is_const_v<T>;
/* ... */
Run Code Online (Sandbox Code Playgroud)
在幕后,概念只不过是取决于模板参数的编译时布尔常量(编辑:否!请参阅接受的答案)。甚至requires-clauses 也可以与变量模板一起使用,因为它们只是在编译时计算为布尔值的表达式。