【发布时间】:2019-07-15 22:09:05
【问题描述】:
我不确定为什么以下代码块可以编译和工作,即使模板语法隐含的语义不同。类A 接受模板类型Data 并包含模板类型Data 的成员data。它还有一个构造函数,它按值接受Data 的实例,并使用假定的复制构造函数实例化成员data。另一个类C 有一个任意构造函数,它接受一个指向任意类B 的指针并将其存储为成员foo。当A 中的Data 被模板化为C 类型并使用C 的构造函数接受的参数实例化A<C>(即,指向B 的指针)时,人们会期待编译器错误,因为@ 987654338@ 尚未被告知如何处理任意参数并将它们传递给Data 构造函数。它只被告知将Data 的复制构造函数与现有实例一起使用。但是,此代码使用 clang 和 c++11 编译并打印为 true。我假设这是一个编译器错误,而不是一个功能,但也许我错过了一些关于 C++ 模板如何工作的东西?我也很好奇这个功能的正确语法是,(将任意模板参数传递给A的构造函数并将它们转发给Data类型的构造函数),因为这是我的实际意图。
#include <iostream>
template<typename Data>
struct A {
Data data;
A(Data data_) : data(data_) { }
};
struct B {
B() { }
};
struct C {
B* foo;
C(B* foo_) : foo(foo_) { }
};
int main() {
B foo;
A<C> thing = A<C>(&foo);
std::cout << (thing.data.foo == &foo) << std::endl;
return 0;
}
编辑:
正确的方法是parameter packing
template<typename Data>
struct A {
Data data;
template<class ... Args>
A(Args... args) : data(std::forward<Args>(args)...) { }
};
struct B {
B() { }
};
struct C {
B* foo;
C(B* foo_) : foo(foo_) { }
};
int main() {
B foo;
A<C> thing = A<C>(&foo);
std::cout << (thing.data.foo == &foo) << std::endl;
return 0;
}
【问题讨论】:
-
如果您将
A设为不是模板,同样的事情也会发生。这是一个隐式转换 -
有趣,刚刚尝试过,你完全正确。对我来说似乎很奇怪,是否有关于此功能的文档?
-
cppreference 并不是最容易阅读,但非常准确。
-
@Justin 请将此扩展为答案。否则,我们只有老鼠的糟糕尝试。