可能的编译器错误?使用从模板化静态成员函数检索的指针调用模板化方法时,无法进行自动推理
Possible compiler bug? auto deduction isn't possible when calling a templated method with a pointer retrieved from a templated static member function
UPDATE 2
为什么这被标记为重复项? Where and why do I have to put the “template” and “typename” keywords?
没有回答这个问题。此处描述的行为在任何地方都没有提及(您不会在那里找到有关auto
的预期行为的单个注释(。
这不是重复的,特别是因为不同的编译器中存在冲突的行为。
更新
就像GCC一样,clang也无法编译:
17 : error: expected expression
return p->is<true>();
^
但是,在 MSVC 上,具有auto
检测的代码已成功编译。
显然,某处存在编译器错误。
现场示例
请考虑以下类:
struct A {
template<bool>
bool is() const {
return true;
}
template<bool>
static A* get() {
static A a;
return &a;
}
};
如果模板函数,例如
template<bool cond>
bool foo() {
auto p = A::get<cond>();
return p->is<true>();
}
尝试调用A::is<bool>
,失败惨败:
main.cpp: In function 'bool foo()':
main.cpp:17:24: error: expected primary-expression before ')' token
return p->is<true>();
^
main.cpp: In instantiation of 'bool foo() [with bool cond = true]':
main.cpp:21:22: required from here
main.cpp:17:17: error: invalid operands of types '<unresolved overloaded function type>' and 'bool' to binary 'operator<'
return p->is<true>();
^
但是,如果只有我们将auto
替换为显式类型(A*
(:
template<bool cond>
bool foo() {
A* p = A::get<cond>();
return p->is<true>();
}
它有效。
这是什么原因呢?
写
return p->template is<true>();
因为编译器最初并不知道is
是一个模板。
一些更深刻的解释。跟
A* p = A::get<cond>();
return p->is<true>();
编译器即使在分析代码时也知道p
是 A*
类型,因此它看到p->is
是一个模板。
跟
auto p = A::get<cond>();
return p->is<true>();
编译器最初不知道p
的类型。它只有在实例化A::get<cond>
之后才会知道这一点,而这只有在实例化foo
时才会发生。所以它不知道p->is
是一个模板。(它可能很容易不是一个模板,因为你有专门的A
版本,比如说,true
模板参数。
延伸阅读:我必须在哪里以及为什么必须放置"模板"和"类型名称"关键字?
引用标准 [14.2.4]:
当成员模板专用化的名称出现在 之后时。 或 ->在后缀表达式中或限定 id 中的嵌套名称说明符之后,并且后缀表达式的对象表达式为 类型相关或限定 id 中的嵌套名称说明符引用 到依赖类型,但名称不是当前 实例化 (14.6.2.1(,成员模板名称必须以 关键字模板。否则,该名称被假定为命名 非模板。
我认为这清楚地解释了观察到的是正确的行为。如果没有auto
,p
的类型就不依赖于类型。有了auto
,就变得与类型相关。
- 如何强制从重写方法调用重写的方法基方法?
- C++:使用方法调用析构函数的顺序是什么?
- 派生类调用父类的方法,该方法调用重写的虚拟方法调用错误的方法
- 使用 object 中的方法调用带有 std::bind 和 std::function.target 的 C 样式函数
- 指向类方法调用的指针
- 如何使用 SFINAE 在方法调用中有条件地定义变量?
- 是否有可以处理方法调用依赖关系的设计模式?
- 如何缩短C++中的方法调用?
- 从部分专用模板方法调用模板非静态方法
- 有没有办法禁止派生类中的基类方法调用?
- 为什么这C++只在编译器上编码一个不明确的方法调用Microsoft?
- 从父方法调用子方法
- 如何将子方法调用到父方法
- 虚拟函数在哪里使用 vpointer to vtable 来解析方法调用,非虚拟方法存储在哪里以及如何解析它们?
- 从静态方法调用静态函数指针
- 从同一类中的另一个方法调用方法时出错
- 方法调用意外地像 l 值一样起作用
- 无法从派生的一个方法调用基类方法
- 从类方法调用命名空间中名为 Same 的函数时,重载解析失败
- C 多线程JAVA JNI方法调用