【问题标题】:What template parameter do I use? (C++ conceptual question)我使用什么模板参数? (C++ 概念问题)
【发布时间】:2021-12-24 18:03:15
【问题描述】:

我正在阅读 Josh Lospinoso 的《C++ Crash Course》一书,并且一直在编译课程中的代码。我在使用以下代码时遇到了问题(这是本书中一个示例的简化版本)。

struct SmallStruct {};

template <typename T>
struct BigStruct {
    BigStruct(const T& arg) : arg{arg} {};
private:
    const T& arg;
};

int main() {
    BigStruct main_struct{[](const SmallStruct&) {}};
}

这段代码我看不懂的主要部分是main()中的语句,专门用lambda函数构造的。我知道代码无法编译,因为在 main() 中实例化 BigStruct 对象时,它缺少模板参数。我试过&lt;SmallStruct&gt;&lt;SmallStruct&amp;&gt; 作为参数,但都没有编译。如果有人能解释发生了什么,那将对我的学习非常有益。

【问题讨论】:

  • 欢迎来到 StackOverflow。如果这不能为您编译,则您的编译器可能设置为语言标准的太旧版本。用g++ -std=c++17 编译对我来说很好。模板参数是构造函数参数的类型。
  • 你需要CTAD 来编译。它是在 c++17 中引入的。
  • 感谢工作。那么为什么我们在实例化 BigStruct 对象时不需要提供模板参数呢?是自动推导出来的吗?
  • 谢谢@super 刚刚看到你的链接。很有帮助
  • @Lachlan 构造函数参数需要允许从中推断模板类型,您的示例就是这种情况。例如,默认构造函数不允许这样做,在这种情况下,您仍然必须指定模板参数...

标签: c++ templates lambda constructor


【解决方案1】:

在“旧”时代,方法是使用 make_... 辅助函数来获取从函数参数推导出的模板参数:

struct SmallStruct {};

template <typename T>
struct BigStruct {
    BigStruct(const T& arg) : arg{arg} {};
private:
    const T& arg;
};

template <typename T>
BigStruct<T> make_big_struct(const T& t){
    return {t};
}

int main() {
   auto main_struct = make_big_struct([](const SmallStruct&) {});
}

由于 C++17 存在 CTAD (class template argument deduction),并且您的代码按原样编译而不会出错,因为 T 可以从参数推导出到构造函数 (https://godbolt.org/z/oWrnc6bah)。

【讨论】:

  • 旧时代的另一种变体:auto lambda = ...; BigStruct&lt;decltype(lambda)&gt;bs(lambda); - 如果结构只是函数中的一个小型、专门设计的帮助器类,则特别有用...
  • 请注意,当复制构造函数用于 CTAD 时,“旧”make_XXX 仍然有用(至少在通用代码中)(std::optional(other_optionnal); 返回一个副本,而 std::make_optional(other_optionnal); 会给出std::optional&lt;std::optional&lt;U&gt;&gt;)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-07
  • 2020-05-14
相关资源
最近更新 更多