【问题标题】:C++ class with template member that constructs template member with arbitrary template arguments带有模板成员的 C++ 类,它使用任意模板参数构造模板成员
【发布时间】: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 请将此扩展为答案。否则,我们只有老鼠的糟糕尝试。

标签: c++ c++11 templates


【解决方案1】:

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

通常静态代码分析器会将此标记为不可取,因为您不希望进行此类自动或意外转换。因此,您确实应该使用显式关键字标记所有单参数 ctor。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多