我试图使用一个既适用于内置类型又适用于用户定义类型的概念。在我的设置中,转发声明某些函数是不方便的(因为这些函数间接依赖于导致我问题的概念)。
我的问题是,如果函数具有内置类型的参数,则概念无法识别以前未声明的函数。下面是一个最小的非工作示例:
struct S {};
// void func(bool); // Works if this line uncommented
template<typename T> concept has_func =
requires(T t) { func(t); };
void func(S) {}
static_assert(has_func<S>); // OK
void func(bool) {}
static_assert(has_func<bool>); // Error
我的第一个问题:为什么会发生这种情况?我怀疑这与ADL有关,因为即使一切都在全局命名空间中,全局命名空间仍然是一个命名空间,而bool,内置的,从技术上讲并不在那个命名空间中。所以我需要用一些用户定义的类型来表达这个概念,这些类型捕获bool的行为。
我的第二个问题是:推迟对我的函数进行名称查找的好方法是什么?我的退路(因为我不能在实际代码中进行前向声明)是将这个概念重新定义为< code>std::same_as
更新:
我没有解决此问题的技巧,但我知道这是由依赖名称查找规则引起的。具体说来:
所以我尝试了两件事:
>
使用触发 ADL 类型的额外参数调用其他一些函数 dofunc
。这种工作,除了这个函数需要调用func,所以dofunc
函数的位置现在变得很棘手,func
在范围内。它并没有真正改善事情。
使用带有运算符 bool 的某种代理类型,但这不起作用,因为它不会触发我要调用的函数的 ADL。
这可能是因为我想做的是不可能的,为了避免在不同的上下文中,这个概念意味着不同的情况。当然,ADL的概念在不同的环境中可能会有所不同,这取决于使用概念时的范围,所以我仍然没有真正理解这种限制的理由。
是,static_assert(has_func
我认为你可以使用代理类型< code>A
template<class T>
struct A{
operator T() const;
};
template<typename T> concept has_func =
requires { func(A<T>{}); };
// Some tests:
void func(bool&) {}
static_assert(has_func<bool&>);
static_assert(!has_func<int>); // func(1) is not valid
void func(bool) {}
static_assert(has_func<bool>);
struct S{};
void func(S) {}
static_assert(has_func<S>);
演示:https://gcc.godbolt.org/z/bGY8zGes9