- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
这与 this question 非常相似,但我不确定那里的答案是否完全适用于我放在一起演示问题的最少代码。 (我的代码不使用尾随返回类型,并且还有一些其他差异。)此外,似乎没有解决 MSVC 的行为是否合法的问题。
简而言之,当函数模板位于命名空间内时,我看到编译器选择通用函数模板实例化而不是更具体的重载。
考虑以下一组命名空间和类定义:
namespace DoStuffUtilNamespace
{
template<typename UNKNOWN>
void doStuff(UNKNOWN& foo)
{
static_assert(sizeof(UNKNOWN) == -1, "CANNOT USE DEFAULT INSTANTIATION!");
}
}
class UtilForDoingStuff
{
public:
template <typename UNKNOWN>
void doStuffWithObjectRef(UNKNOWN& ref)
{
DoStuffUtilNamespace::doStuff(ref);
}
};
class MyClassThatCanDoStuff { };
namespace DoStuffUtilNamespace
{
using ::MyClassThatCanDoStuff; // No effect.
void doStuff(MyClassThatCanDoStuff& foo) { /* No assertion! */ }
}
...以及以下用例:
int main()
{
MyClassThatCanDoStuff foo;
DoStuffUtilNamespace::MyClassThatCanDoStuff scoped_foo;
UtilForDoingStuff util;
DoStuffUtilNamespace::doStuff(foo); // Compiles
DoStuffUtilNamespace::doStuff(scoped_foo); // Compiles
util.doStuffWithObjectRef(foo); // Triggers static assert
util.doStuffWithObjectRef(scoped_foo); // Triggers static assert
}
如果整个DoStuffUtilNamespace
被删除并且它的所有成员都被移动到全局范围,这可以很好地使用 G++ 和 Clang++ 进行编译。
使用命名空间,doStuff
当然是从属名称。根据top-voted answer on the similar question ,标准说:
In resolving dependent names, names from the following sources are considered:
Declarations that are visible at the point of definition of the template.
Declarations from namespaces associated with the types of the function arguments both from the instantiation context and from the definition context.
这对我来说似乎有点奇怪;我不明白为什么第一个要点会指定声明必须在模板的定义点而不是在实例化点可见,因为第二个要点明确指定某些声明仅在实例化时可见是允许的。 (如果有人愿意提供理由,我将不胜感激,但这不是我的问题,因为我的理解是“标准委员会为什么决定 X”这种形式的问题不在主题之列。)
所以我认为这解释了为什么 util.doStuffWithObjectRef(foo);
触发静态断言:doStuff(MyClassThatCanDoStuff&)
尚未在 UtilForDoingStuff::doStuffWithObjectRef<UNKNOWN>(UNKNOWN&)
的定义点声明.确实移动了class UtilForDoingStuff
在 doStuff
之后定义 重载已被定义似乎解决了这个问题。
但是标准中所说的“与函数参数类型相关联的命名空间”到底是什么意思?不应该 using ::MyClassThatCanDoStuff
声明,以及 scoped_foo
的明确范围命名空间中的实例类型,触发依赖于参数的查找,并且此查找不应该找到 doStuff()
的非断言定义吗? ?
另外,整个代码使用clang++ -ftemplate-delayed-parsing
编译没有错误,它模拟 MSVC 的模板解析行为。这似乎更可取,至少在这种特殊情况下,因为随时向 namespace 添加新声明的能力是 namespace 的主要吸引力之一。但是,如上所述,根据标准,它似乎并不完全符合法律条文。这是允许的,还是不符合规定的情况?
EDIT:: 正如 KIIV 所指出的,有一个解决方法;如果使用模板特化而不是重载,代码将编译。我仍然想知道有关该标准的问题的答案。
最佳答案
With the namespace,
doStuff
is of course a dependent name.
您的出发点是错误的。对于像 DoStuffUtilNamespace::doStuff(ref)
这样的限定调用,没有 ADL。 [basic.lookup.argdep]/p1,强调我的:
When the postfix-expression in a function call (5.2.2) is an unqualified-id, other namespaces not considered during the usual unqualified lookup (3.4.1) may be searched, and in those namespaces, namespace-scope friend function or function template declarations (11.3) not otherwise visible may be found.
DoStuffUtilNamespace::doStuff
是一个qualified-id,而不是一个unqualified-id。 ADL 不适用。
因此,DoStuffUtilNamespace::doStuff
也不是依赖名称。 [临时部门]/p1:
In an expression of the form:
postfix-expression ( expression-listopt)
postfix-expression 是一个unqualified-id, unqualified-id 表示一个从属名称 if [...]。如果运算符的操作数是依赖于类型的表达式,则该运算符还表示 依赖名称。这些名称是未绑定(bind)的,可以在 模板实例化点(14.6.4.1)在这两个上下文中 模板定义和实例化点的上下文
(相关名称 的斜体表示该段定义了术语。)
相反,根据 [temp.nondep]/p1:
Non-dependent names used in a template definition are found using the usual name lookup and bound at the point they are used.
找不到您稍后的重载声明。
特化之所以有效,是因为它仍然使用相同的函数模板声明;您只是提供了与默认实现不同的实现。
But what exactly does the standard mean by "namespaces associated with the types of the function arguments"? Shouldn't the
using ::MyClassThatCanDoStuff
declaration, together with the explicit scoping of the scoped_foo instance type within the namespace, trigger argument-dependent lookup
没有。 using-declaration 不会影响 ADL。 [basic.lookup.argdep]/p2,强调我的:
For each argument type
T
in the function call, there is a set of zero or more associated namespaces and a set of zero or more associated classes to be considered. The sets of namespaces and classes is determined entirely by the types of the function arguments (and the namespace of any template template argument). Typedef names and using-declarations used to specify the types do not contribute to this set. The sets of namespaces and classes are determined in the following way:
If T is a fundamental type, [...]
If T is a class type (including unions), its associated classes are: the class itself; the class of which it is a member, if any; and its direct and indirect base classes. Its associated namespaces are the innermost enclosing namespaces of its associated classes. Furthermore, if T is a class template specialization, its associated namespaces and classes also include: the namespaces and classes associated with the types of the template arguments provided for template type parameters (excluding template template parameters); the namespaces of which any template template arguments are members; and the classes of which any member templates used as template template arguments are members. [ Note: Non-type template arguments do not contribute to the set of associated namespaces. —end note ]
[...]
关于c++ - 命名空间导致次优模板重载解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32235765/
我面临以下问题: 我有一个命名空间 Exception\* , 其中包含多种类型 异常(exception)。 我有一个命名空间 Exception\User\* ,其中包含一个 特定类型的异常 (
新的 Highcharts v3.0 气泡图看起来很棒。是否可以用名称/一些文本注释和显示每个气泡? 谢谢,奈杰尔。 最佳答案 您需要做两件事。 首先,命名每个数据点(气泡): data: [ {
我通过使用 EVP_get_cipherbyname("AES-256-CTR") 获得了 EVP_CIPHER*,现在我想找到一种方法从 EVP_CIPHER* 返回到原始名称,在本例中为“AES-
为了避免 JavaScript 堆问题,我使用多个数组:family1、family2、family3 ...、dogs1、dogs2、dogs3 ... 使用示例:“family1 和 dogs1”
我很难理解这段代码。这不是我熟悉的典型 Javascript 函数语法。这是一个命名函数吗?或者这是更新事件的回调?抱歉,我对新手问题很陌生,我对 JS 还很陌生。我了解正在发生的一切,除了这个函数语
是否可以在 python 中执行以下操作? i=1 while True: w = open("POSCAR_i","w") i=i+1 if i<10:
我问这个是因为我刚刚在一段代码上看到它: var myVar = function func(arg){ console.log(arg); } 我不明白为什么函数在为 myVar 定义之前被“
我正在尝试为 ActiveDirectory 创建上下文(客户端和服务器都是 Windows),使用我的 Windows 凭据和 NTLM。 这是我的代码: public void func() {
我正在运行一个使用 JBoss5 容器的 ejb 示例。我正在使用一个例子 from here(Part one) . 在示例中,我在 JBoss 中部署了 bean,在 Tomcat 中部署了一个应
我希望能够命名一个 BackgroundWorker 以便于调试。这可能吗? 最佳答案 我必须尝试,但你不能只设置 Name BackgroundWorker 执行的 DoWork() 方法中的线程?
我在 Android Activity 和其他类之间遇到了越来越多的命名冲突。我想知道你能不能告诉我你是如何避免这些的。遗憾的是,关于 SO 的相关问题并未涵盖我的特定命名问题。 第一个例子 我有一个
当我尝试使用 loadChildren 加载模块以在命名 socket 中加载模块的组件时,出现抛出错误。 有没有办法在命名的路由器 socket 中延迟加载模块? //html //routing
很难说出这里问的是什么。这个问题是模棱两可的、模糊的、不完整的、过于宽泛的或修辞的,无法以目前的形式得到合理的回答。如需帮助澄清这个问题以便重新打开它,visit the help center .
在 Type Driven Development with Idris 第 6 章的代码中,我对这段代码感到困惑: data DataStore : Type -> Type where M
通常,如果有一个属性可以获取/设置状态值,我会使用“Is”,例如: Visibility: .IsVisible 但是对于获取/设置操作的属性,最好使用什么?喜欢: Casting shadows:
好的,所以如果你可以很容易地想到一个名词,那么命名一个接口(interface)(或类)很容易:用户、窗口、数据库、流等。 形容词或形容词的概念呢?例如有时间戳的东西(HasTimestamp、Tim
我刚开始学习 PowerShell,我想知道 Posh 中的 cmdlet(或高级功能,无论它们在 CTP3 中称为什么)是否有一些好的动词指南。 如果我做一个get-verb,我可以看到很多。但我仍
$(".song").live('click', function songClick() { //do stuff }); 你能像上面那样命名一个函数,然后稍后再调用它吗?我尝试过,但没有成
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 可以用事实和引用来回答它. 7年前关闭。 Improve this
我的 Spring 应用程序中有两组类 - DTO 和实体。 在阅读了 Bob 叔叔的 Clean Code 之后,我比以往任何时候都更喜欢正确命名事物。 我坐下来重构我的一个 Spring 项目,但
我是一名优秀的程序员,十分优秀!