簡體   English   中英

成員變量與函數概念檢查

[英]Member variable vs. function concept checking

我沉迷於一些早期的星期天 C++20 惡作劇,在玩 gcc/clang 主干概念時,我偶然發現了一個我沒有看到優雅解決方案的問題。 考慮這個代碼:

template <typename T>
concept floating_point = std::is_floating_point_v<std::decay_t<T>>;

template <typename T>
concept indexable = requires(T v)
{
    {v[0]} -> floating_point;
    {v[1]} -> floating_point;
    {v[2]} -> floating_point;
};

template <typename T>
concept func_indexable = requires(T v)
{
    {v.x()} -> floating_point;
    {v.y()} -> floating_point;
    {v.z()} -> floating_point;
};

template <typename T>
concept name_indexable = requires(T v)
{
    {v.x} -> floating_point;
    {v.y} -> floating_point;
    {v.z} -> floating_point;
};

template <typename T>
concept only_name_indexable = name_indexable<T> && !indexable<T>;

template <typename T>
concept only_func_indexable = func_indexable<T> && !indexable<T> && !name_indexable<T>;

void test_indexable(indexable auto v) {
    std::cout << v[0] << " " << v[1] << " " << v[2] << "\n";
}

void test_name_indexable(only_name_indexable auto v) {
    std::cout << v.x << " " << v.y << " " << v.z << "\n";
}

void test_func_indexable(only_func_indexable auto v) {
    std::cout << v.x() << " " << v.y() << " " << v.z() << "\n";
}

(玩這個的強制性godbolt) https://godbolt.org/z/gyCAQn

現在考慮一個滿足only_func_indexable的結構/類:擁有成員函數x()y()z()立即導致name_indexable概念檢查中的編譯錯誤。 更確切地說:

<source>: In instantiation of 'void test_func_indexable(auto:3) [with auto:3 = func_point]':

<source>:125:26:   required from here

<source>:29:6: error: 'decltype' cannot resolve address of overloaded function

   29 |     {v.x} -> floating_point;

這有點明顯,因為.x指的是成員函數的名稱,它是decltype內部的非法表達式。 另請注意,將name_indexable的定義更改為

template <typename T>
concept name_indexable = !func_indexable<T> && requires(T v)
{
    {v.x} -> floating_point;
    {v.y} -> floating_point;
    {v.z} -> floating_point;
};

通過懶惰的聯合評估解決了這個問題。

在這一點上,我的結論是:“每當我想檢查成員變量是否存在時,我必須首先提供並檢查一個概念是否存在類似命名的成員函數”。

現在這感覺相當尷尬,就像 ISO 組中的優秀人員想到了一個更優雅的解決方案一樣。

在這種情況下,該解決方案是什么?

最好的,理查德

我不確定你的問題是否真的有問題。 希望您永遠不會擁有同時具有數據成員x和成員函數x ,因此您的func_indexable已經是only_func_indexable ,有了這個概念,就沒有問題了。

但是如果你想在那里非常精確,你可以做這樣的事情

requires std::is_member_object_pointer_v<decltype(&T::x)> && floating_point<std::invoke_result_t<decltype(&T::x), T>>;

當然,這應該打包成一些概念,而不是每次都寫。 注意std::invoke_result_t<decltype(&T::x), T>給出(一些參考) float兩個float x; float x(); .

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM