【问题标题】:Using c++ 20 Concept to check if a function returns a const value使用 c++ 20 Concept 检查函数是否返回 const 值
【发布时间】:2021-01-11 00:00:34
【问题描述】:

我正在尝试使用概念,以便能够检测给定类型的开始函数是否将迭代器返回到“const T&”或仅返回“T&”。但我不确定如何最好地去做,我尝试了以下方法:

#include <iostream>
#include <concepts>
#include <vector>
#include <set>

template <typename T>
concept IsConst = std::is_const<T>::value;

template<typename T>
concept IsIterableOfConst = requires (T& t) { { *t.begin() } -> IsConst; };

template <IsIterableOfConst T>
void test()
{
    std::cout << "Yes" << std::endl;
}

template <typename T>
void test()
{
    std::cout << "No" << std::endl;
}


int main(int argc, char** argv)
{
    test<std::set<int>>();
    test<std::vector<int>>();
}

当我希望它产生输出“Yes No”时,这会产生输出“No No”,因为据我所知,std::set 中的迭代器应该总是迭代设置持有类型。如何正确检测容器包含 const 值?

【问题讨论】:

  • "如何正确检测容器包含 const 值?" 我不知道为什么问一个范围是有用的。如果您要约束的函数不会对元素进行任何修改,那么它为什么要关心范围是否为 const 呢?毕竟,如果您有非常量左值,则仍然可以调用以const &amp; 为参数的函数。为什么范围不应该是这样的?

标签: c++ c++20 c++-concepts


【解决方案1】:

这里的直接问题是std::set&lt;int&gt;decltype((*t.begin())) 为您提供int const&amp; 类型,而std::is_const&lt;T&gt; 类型特征检查T 是否是某个类型U const。引用不是 const。

您需要先剥离参考:

template <typename T>
concept IsConst = std::is_const_v<std::remove_reference_t<T>>;

也就是说,这并不是一个完全正确的常量检查。考虑views::iota(0, 10) 的范围,它可以根据需要为您提供一堆整数。这个范围的引用类型是int(不是int&amp;,不是int const&amp;,只是int)。这不是 const 类型,因此您的概念会说这样的范围不适合 IsIterableOfConst (旁注:术语是范围,不可迭代)。但这样的范围确实是 const - 你不能修改它的内容。

所以更接近的答案是:

template <typename T>
inline constexpr bool is_suitably_const = true;

template <typename T>
inline constexpr bool is_suitably_const<T&> = is_const_v<T>;

template <typename R>
concept RangeOfConst = range<R> && is_suitably_const<range_reference_t<R>>;

这表示vector&lt;int&gt; 不是RangeOfConstset&lt;int&gt;vector&lt;int&gt; constiota_view&lt;int&gt; 也是。

但是...它也会说vector&lt;bool&gt;RangeOfConst,即使您可以修改它们!我会把它留作未来的思考。

【讨论】:

    【解决方案2】:

    直接的方法是如果T是const,那么T应该和add_const_t&lt;T&gt;是同类型的,所以你只需要把你的IsConst改成

    template <typename T>
    concept IsConst = std::is_same_v<T, std::add_const_t<T>>;
    

    【讨论】:

    • 也可以只使用T const 而不是std::add_const_t&lt;T&gt;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-18
    • 1970-01-01
    • 1970-01-01
    • 2015-12-12
    • 1970-01-01
    • 1970-01-01
    • 2013-04-11
    相关资源
    最近更新 更多