gpt4 book ai didi

c++ - Argument Dependent Lookup 的逆向解决方法?

转载 作者:可可西里 更新时间:2023-11-01 16:42:33 25 4
gpt4 key购买 nike

C++ 具有 ADL(参数相关查找),正如其名称所描述的那样,函数的上下文(命名空间)可以从(任何)参数的上下文(命名空间)中隐含。

fun(a); // if the type of a is in namespace ns deduce ns::f if available

我的问题是,是否也可以通过某种技术进行反向操作? 我所说的反向是指上下文(命名空间)是否可以从被调用函数的上下文中推导出来。某种“功能相关查找”(FDL)。假代码:

ns::fun(a); // deduce ns::a if available

我想不出这样做的方法。对于用于对函数选项进行编码的 enum,此限制尤其烦人。我想知道是否有一种技术可以模拟此功能(C++11 也可以)。假代码:

ns::fun(Saturday, Tuesday); // Saturday/Tuesday are enum values in namespace ns;

特别是如果枚举有变通方法的话。

这段代码说明了这个问题:

namespace longname{
class A{};
void fun(A const& a){}
A global_a;

enum Days { Saturday,Sunday,Tuesday,Wednesday,Thursday,Friday};
void gun(Days d1, Days d2){}
}

int main(){
longname::A a;
fun(a); // cool, longname::fun(a) not necessary, fun is deduced from context

longname::fun(global_a); // error, not cool, global_a context not deduced,
// must use then longname::fun(longname::global_a)
longname::gun(Saturday, Tuesday); // error, particularly not cool, the Saturday is not deduced from context
// must use then longname::gun(longname::Saturday, longname::Tuesday)
// or at best gun(longname::Saturday, longname::Tuesday)
}

编辑: @jrok 建议了一种基于定义嵌套命名空间的解决方法。对于 enum 案例,我得到了这段代码。这仍然有一些噪音(实际上根本没有“依赖”查找),但这是一个改进。

namespace longname{
namespace days{
enum _ { Saturday,Sunday,Tuesday,Wednesday,Thursday,Friday};
}
void gun(days::_ d1, days::_ d2){}
}

int main(){
using namespace longname::days; // some noise still here
longname::gun(Saturday, Tuesday);
}

我没有使用 enum class 因为 SaturdaySunday 等不能直接在范围内使用(实际上 使用longname::days::_ 会给我一个编译错误)

最佳答案

是也不是。大多数情况下没有。

坏消息是,如果一个枚举在当前范围之外,例如 Tuesday 等,那么它就不能传递给一个函数,即使该函数是在一个命名空间中声明的枚举是可见的。这是因为当您编写函数调用并且参数无法传递给 gun 时,首先会发生参数查找,然后才会发生名称查找。没有什么可以改变这一点 - 但也有好消息。

首先,您似乎需要映射 ns::foo(arg1, arg2) -> {using namespace ns; 的行为。 ns::foo(arg1, arg2);。函数调用和模板不能改变这一点,但宏可以,我包括了示例。

我还给出了一个参数依赖查找的基本示例。您可以看到使用此机制可以找到超出范围的函数 GetMonday 和 GetTuesday(它们返回超出范围的枚举),因为您包含了该命名空间中的一种类型。 RegisterNamespace::val 在编译器尝试查找 GetMonday 时将隐藏的命名空间添加到作用域中,并且 GetMonday 返回一个 Days,它允许编译器查找 foo.

您真的希望编译器在遇到来自另一个命名空间的函数时通过添加额外的命名空间来改变作用域。然而,编译器此时已经确定了参数的类型,并且实际上需要它们来计算出该函数的其他可能替代方案。

#include <iostream>

namespace hidden {

enum RegisterNamespace { val };

enum Days {
Monday,
Tuesday
};

void foo(Days a , Days b){std::cout << "Called foo\n";}

Days GetMonday(RegisterNamespace a = val){return Days::Monday;}
Days GetTuesday(RegisterNamespace b = val){return Days::Tuesday;}

}

using namespace std;

#define UseNamespace(ns, x) do {using namespace ns; x;} while (0)

int main()
{
//with a macro
UseNamespace(hidden,hidden::foo(Monday, Tuesday));

{
//foo is found by argument dependent lookup
using hidden::Days;
foo(Days::Monday,Days::Tuesday);
}

{
using r = hidden::RegisterNamespace;
//foo and GetMonday / GetTuesday are all found by argument dependent lookup
foo(GetMonday(r::val),GetTuesday(r::val));
}

return 0;
}

关于c++ - Argument Dependent Lookup 的逆向解决方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20600413/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com