我沉迷于一些星期日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";
}
(obligatory godbolt for toying with this) https://godbolt.org/z/gyCAQn
现在考虑满足only_func_indexable
的结构/类:具有成员函数x()
,y()
和z()
会立即导致{{ 1}}。更精确地:
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
通过惰性合取评估解决了问题。
在这一点上,对我来说,收获是:“每当我想检查成员变量的存在时,我必须首先提供并检查一个不存在类似名称的成员的概念功能”。
现在这感觉很尴尬,就像设置ISO组中的优秀人员在脑海中想到一个更优雅的解决方案一样。
在这种情况下该解决方案是什么?
最好, 理查德
答案 0 :(得分:0)
我不确定您的问题是否确实存在。希望您永远不会拥有同时具有数据成员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();
的引用。)