C++ 类构造时隐式转换的小疑惑

2020-05-24 11:57:20 +08:00
 Tony042

最近在学 C++的相关知识,在学习类模板参数的辅助自动推导时,有了些疑问,请看下面代码:

template <typename T, typename Cont = std::vector<T>>
class Stack
{
private:
    Cont elems;
public:
    Stack() = default;
    Stack(Stack const &) = default;
    Stack(T const &elem) : elems({elem}) {}
};

Stack(char const *)->Stack<std::string>; // CATD

在构造这个类的时候:

Stack stringStack = "bottom";  // MSVC  16.9 编译通过,GCC-10 编译不通过
Stack stringStack{"bottom"};   // MSVC  16.9 和 GCC-10 均编译通过

请问为什么第一个构造方式 GCC 编译不通过呢,是否是因为 MSVC 又启用了某些魔改插件?个人理解是从 Char const[7]或 char const* 转换到 string 算一次转换,然后从 string 到 Stack 进行了二次转换,而 C++只允许进行一次隐式转换,不知是否正确

2937 次点击
所在节点    C++
26 条回复
Tony042
2020-05-24 22:27:53 +08:00
@constexpr 这玩意真的好复杂,不知道这编译器都是咋写出来的
Wirbelwind
2020-05-26 12:39:37 +08:00
这个推导指引被视为 函数了
Wirbelwind
2020-05-26 13:26:41 +08:00
@Wirbelwind 之前只看了提示报错,测试不充分

---
Stack stringStack{"bottom"};
这句可以过是因为 Stack(T const &elem),这里定义的第三个构造函数,如果把去掉是编译不过的 提示也是类型转换问题。

---
这里的问题主要是 模板生成时不允许强制转换
Wirbelwind
2020-05-26 14:02:15 +08:00
Stack(char const *)->Stack<std::string>
这里因为你指引了一个模板 所以应该提供一个专用的 构造函数。

建议不要学模板这么复杂的功能,心智负担太大。
以上分析不保证正确
Tony042
2020-05-26 23:18:46 +08:00
@Wirbelwind #23 是这个构造函数在起作用,我疑惑的地方是,传入引用 ( T const& elem)为什么可以发生 type decay 也就是 char const[7] -> char const *,一般只有传入值的时候会 type decay
Wirbelwind
2020-05-27 09:18:12 +08:00
@Tony042 生成模板代码的时候 那里固定成了 std::string,但是 std::string 好像没有数组的构造函数,然后转换成了 char*

大概是这样

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/674867

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX