从另一个模板对象调用模板方法时出现奇怪的编译行为
Strange compilation behaviour when calling a template method from another template object
有人能解释一下为什么下面的c++代码没有按预期运行吗:
struct Object {
template< int i >
void foo(){ }
};
template<int counter>
struct Container {
Object v[counter];
void test(){
// this works as expected
Object a; a.foo<1>();
// This works as well:
Object *b = new Object(); b->foo<1>();
// now try the same thing with the array:
v[0] = Object(); // that's fine (just testing access to the array)
# if defined BUG1
v[0].foo<1>(); // compilation fails
# elif defined BUG2
(v[0]).foo<1>(); // compilation fails
# elif defined BUG3
auto &o = v[0];
o.foo<1>(); // compilation fails
# else
Object &o = v[0];
o.foo<1>(); // works
# endif
}
};
int main(){
Container<10> container;
}
上面的代码在没有标志的情况下编译得很好。如果设置了标志BUG1到BUG3中的一个,则编译失败,出现GCC 4.6或4.7以及clang 3.2(这似乎表明它不是GCC错误)。
第21到29行在语义上做着完全相同的事情(即调用Object数组第一个元素的方法),但只有最后一个版本编译。只有当我尝试从模板对象调用模板化方法时,问题才会出现。
BUG1只是编写呼叫的"正常"方式。
BUG2也是一样,但数组访问受括号保护,以防出现优先级问题(但不应该有)。
BUG3表明类型推理也不起作用(需要使用c++11支持进行编译)。
上一个版本运行良好,但我不明白为什么使用临时变量来存储引用可以解决问题。
我很想知道为什么其他三个无效。
感谢
您必须将template
用作:
v[0].template foo<1>();
auto &o = v[0];
o.template foo<1>();
因为v
的声明依赖于模板参数,这使得v
成为一个依赖名称。
这里template
关键字告诉编译器,后面的任何内容都是模板(在您的情况下,foo
实际上是一个模板)。如果foo
不是模板,则不需要template
关键字(事实上,这将是一个错误)。
问题是o.foo<1>()
可以通过两种方式进行解析/解释:一种方式正如您所期望的(函数调用),另一种方式如下:
(o.foo) < 1 //partially parsed
也就是说,foo
是一个成员数据(而不是函数),您已经将其与1
进行了比较。因此,要告诉编译器<
不是用来比较o.foo
和1
的,而是用来将模板参数1
传递给函数模板的,需要使用template
关键字。
在模板中,表达式可以是依赖于类型的或依赖于值的 类型和表达式可能取决于模板参数的类型和/或值 在您的例子中,counter
是一个模板参数,v
的声明依赖于它,使v[0]
成为一个依赖于foo
是一个依赖名称,您必须通过说:来消除作为模板名称的歧义
v[0].template foo<1>();
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 我可以将一个用clang c++11编译的对象与另一个用c++17编译的对象链接起来吗
- C++代码以测试另一个.cpp如果可以编译它
- 编译问题 C++ 同时,尝试通过调用另一个对象中的成员函数来创建 std:: 线程
- 将 lambda 函数转换为另一个编译单元中的普通函数会缩短编译时间吗?
- 在 NDK 上编译两个带有 gradle 的项目,其中一个依赖于另一个的二进制文件
- 为什么有条件编译运算符模板会更改另一个运算符的可用性?
- 如何 G++ 编译另一个目录中具有依赖项的.cpp文件
- 模板函数,它使用 n_copy 复制前 n 个元素形成一个向量,另一个向量导致编译错误
- 两次相同的 for 循环:一个编译,另一个不编译
- 从另一个模板对象调用模板方法时出现奇怪的编译行为
- g++编译存在于另一个目录中的源文件
- C++ 使用另一个类的 typedef'ed 成员时出现编译错误
- 是否对在另一个Linux发行版中使用G 编译的可执行文件有限制
- 编译错误:"指针只能从另一个指针中减去"
- 仅在编辑另一个类后编译更改
- 一些C++代码在一个项目中出错,而在另一个项目中编译良好
- 在另一个进程提供的指针上使用 typeid 是否安全,该进程由同一编译器编译
- 代码块:需要在另一个项目中编译src
- 在另一个类的函数中返回一个类,反之亦然,编译错误(递归)