提问者:小点点

有没有一种方法可以将非ADL名称查找推迟到使用C语言概念的时候?


我试图使用一个既适用于内置类型又适用于用户定义类型的概念。在我的设置中,转发声明某些函数是不方便的(因为这些函数间接依赖于导致我问题的概念)。

我的问题是,如果函数具有内置类型的参数,则概念无法识别以前未声明的函数。下面是一个最小的非工作示例:

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查找检查具有从模板定义上下文可见的外部链接的函数声明
  • ADL检查具有从模板定义上下文或模板实例化上下文可见的外部链接的函数声明

所以我尝试了两件事:

>

  • 使用触发 ADL 类型的额外参数调用其他一些函数 dofunc。这种工作,除了这个函数需要调用func,所以dofunc函数的位置现在变得很棘手,func在范围内。它并没有真正改善事情。

    使用带有运算符 bool 的某种代理类型,但这不起作用,因为它不会触发我要调用的函数的 ADL。

    这可能是因为我想做的是不可能的,为了避免在不同的上下文中,这个概念意味着不同的情况。当然,ADL的概念在不同的环境中可能会有所不同,这取决于使用概念时的范围,所以我仍然没有真正理解这种限制的理由。


  • 共1个答案

    匿名用户

    是,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