Constrain function argument to allocators using C++20 concepts

huangapple go评论68阅读模式
英文:

Constrain function argument to allocators using C++20 concepts

问题

以下是您要翻译的代码部分:

我想要限制构造函数只接受分配器作为参数,并且我提出了这个概念:

#include <iostream>
#include <string>
#include <memory>
#include <memory_resource>
#include <vector>
#include <concepts>
#include <utility> /* declval */

template <typename Allocator> 
concept is_allocator = requires(Allocator a) {
    typename Allocator::value_type;
    { a.allocate(std::declval<std::size_t>()) } -> std::same_as<typename Allocator::value_type*>;
    { a.deallocate(std::declval<typename Allocator::value_type>(), std::declval<std::size_t>()) } -> std::same_as<void>;
};

template <typename T>
struct MyAllocator {
    using value_type = T;
    auto allocate(std::size_t size) -> T*;
    auto deallocate(T*, std::size_t size) -> void;
};

int main() {
    using A1 = std::allocator<int>;
    using A2 = std::pmr::polymorphic_allocator<std::byte>;
    using B = MyAllocator<int>;
    using C = std::string;

    if constexpr(is_allocator<A1>) {
        std::cout << "A1 is an allocator" << std::endl;
    }
    if constexpr(is_allocator<A2>) {
        std::cout << "A2 is an allocator" << std::endl;
    }
    if constexpr(is_allocator<B>) {
        std::cout << "B is an allocator" << std::endl;
    }
    if constexpr(is_allocator<C>) {
        std::cout << "C is an allocator" << std::endl;
    }
}

我将代码部分翻译好了,没有包含其他内容。

英文:

I wanted to constrain a constructor to take only allocators as arguments and I came up with this concept:

Demo

#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;memory&gt;
#include &lt;memory_resource&gt;
#include &lt;vector&gt;
#include &lt;concepts&gt;
#include &lt;utility&gt; /* declval */
template &lt;typename Allocator&gt; 
concept is_allocator = requires(Allocator a) {
typename Allocator::value_type;
{ a.allocate(std::declval&lt;std::size_t&gt;()) } -&gt; std::same_as&lt;typename Allocator::value_type*&gt;;
{ a.deallocate(std::declval&lt;typename Allocator::value_type&gt;(), std::declval&lt;std::size_t&gt;()) } -&gt; std::same_as&lt;void&gt;;
};
template &lt;typename T&gt;
struct MyAllocator {
using value_type = T;
auto allocate(std::size_t size) -&gt; T*;
auto deallocate(T*, std::size_t size) -&gt; void;
};
int main() {
using A1 = std::allocator&lt;int&gt;;
using A2 = std::pmr::polymorphic_allocator&lt;std::byte&gt;;
using B = MyAllocator&lt;int&gt;;
using C = std::string;
if constexpr(is_allocator&lt;A1&gt;) {
std::cout &lt;&lt; &quot;A1 is an allocator&quot; &lt;&lt; std::endl;
}
if constexpr(is_allocator&lt;A2&gt;) {
std::cout &lt;&lt; &quot;A2 is an allocator&quot; &lt;&lt; std::endl;
}
if constexpr(is_allocator&lt;B&gt;) {
std::cout &lt;&lt; &quot;B is an allocator&quot; &lt;&lt; std::endl;
}
if constexpr(is_allocator&lt;C&gt;) {
std::cout &lt;&lt; &quot;C is an allocator&quot; &lt;&lt; std::endl;
}
}

I expected it to detect allocators in A1, A2, B and C case but it doesn't detect a single allocator. Why does this concept not hold true?

答案1

得分: 2

My bad, forgot a '*'... Here's the corrected version that works correctly (credits to @康桓瑋 for more conciseness)!

Demo

#include <iostream>
#include <string>
#include <memory>
#include <memory_resource>
#include <vector>
#include <concepts>

template <typename Allocator> 
concept is_allocator = requires(Allocator a, typename Allocator::value_type* p) {
    { a.allocate(0) } -> std::same_as<decltype(p)>;
    { a.deallocate(p, 0) } -> std::same_as<void>;
};

template <typename T>
struct MyAllocator {
    using value_type = T;
    auto allocate(std::size_t size) -> T*;
    auto deallocate(T*, std::size_t size) -> void;
};

int main() {
    using A1 = std::allocator<int>;
    using A2 = std::pmr::polymorphic_allocator<std::byte>;
    using B = MyAllocator<int>;
    using C = std::string;

    if constexpr(is_allocator<A1>) {
        std::cout << "A1 is an allocator" << std::endl;
    }
    if constexpr(is_allocator<A2>) {
        std::cout << "A2 is an allocator" << std::endl;
    }
    if constexpr(is_allocator<B>) {
        std::cout << "B is an allocator" << std::endl;
    }
    if constexpr(is_allocator<C>) {
        std::cout << "C is an allocator" << std::endl;
    }
}
英文:

My bad, forgot a '*'... Here's the corrected version that works correctly (credits to @康桓瑋 for more conciseness)!

Demo

#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;memory&gt;
#include &lt;memory_resource&gt;
#include &lt;vector&gt;
#include &lt;concepts&gt;
template &lt;typename Allocator&gt; 
concept is_allocator = requires(Allocator a, typename Allocator::value_type* p) {
{ a.allocate(0) } -&gt; std::same_as&lt;decltype(p)&gt;;
{ a.deallocate(p, 0) } -&gt; std::same_as&lt;void&gt;;
};
template &lt;typename T&gt;
struct MyAllocator {
using value_type = T;
auto allocate(std::size_t size) -&gt; T*;
auto deallocate(T*, std::size_t size) -&gt; void;
};
int main() {
using A1 = std::allocator&lt;int&gt;;
using A2 = std::pmr::polymorphic_allocator&lt;std::byte&gt;;
using B = MyAllocator&lt;int&gt;;
using C = std::string;
if constexpr(is_allocator&lt;A1&gt;) {
std::cout &lt;&lt; &quot;A1 is an allocator&quot; &lt;&lt; std::endl;
}
if constexpr(is_allocator&lt;A2&gt;) {
std::cout &lt;&lt; &quot;A2 is an allocator&quot; &lt;&lt; std::endl;
}
if constexpr(is_allocator&lt;B&gt;) {
std::cout &lt;&lt; &quot;B is an allocator&quot; &lt;&lt; std::endl;
}
if constexpr(is_allocator&lt;C&gt;) {
std::cout &lt;&lt; &quot;C is an allocator&quot; &lt;&lt; std::endl;
}
}

huangapple
  • 本文由 发表于 2023年6月29日 23:08:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76582347.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定