具有模板成员的C ++类,可使用任意模板参数构造模板成员

时间:2019-07-15 22:09:05

标签: c++ c++11 templates

即使模板语法所隐含的语义不同,我也不知道为什么下面的代码块能够编译和运行。类A接受模板类型Data,并包含模板类型data的成员Data。它还具有一个构造函数,该构造函数按值接受Data的实例,并使用假定的复制构造函数实例化成员data。另一个类C具有一个任意构造函数,该构造函数采用指向某个任意类B的指针并将其存储为成员foo。当Data中的A模板化为C类型,并且A<C>实例化了C的构造函数接受的参数(即指向{{ 1}})可能会遇到编译器错误,因为尚未告知B如何处理任意参数并将其传递给A构造函数。仅被告知将Data的副本构造函数与现有实例一起使用。但是,此代码使用clang和c ++ 11进行编译并显示true。我假设这是一个编译器错误,而不是功能,但也许我缺少有关C ++模板工作方式的信息?我也对此功能的正确语法感到好奇,(将任意模板参数传递给Data的构造函数,并将它们转发给类型A的构造函数)是我的实际意图。

Data

编辑:

正确的方法是parameter packing

#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;
}

1 个答案:

答案 0 :(得分:0)

编译代码的原因是因为struct C的构造函数未标记为显式。实际上,A<C>对象在其构造函数中需要一个C对象。但是您提供了一个指向b的指针。由于没有将单个参数ctor标记为显式的,因此编译器选择从输入参数到所需参数的适当转换是合法的。

通常,静态代码分析器会将其标记为不受欢迎的,因为您永远不需要这种自动或意外的转换。因此,您确实应该使用显式关键字标记所有单个参数ctor。

https://en.cppreference.com/w/cpp/language/explicit