如何让cArray类模板无需转换即可调用单参数构造函数?
cArray构造函数歧义问题的解决方案
修改后的代码实现
#include <concepts> #include <cstddef> #include <initializer_list> #include <vector> template <typename T> class cArray { private: std::vector<T> data; public: // 指定数组大小的构造函数 explicit cArray(std::size_t size) : data(size) {} // 初始化列表构造函数 - 用于单个/多个元素的直接初始化 cArray(std::initializer_list<T> init) : data(init) {} // 变参构造函数 - 支持多参数元素初始化,排除单个整数参数的歧义场景 template <typename... Elements> requires std::constructible_from<T, Elements&&...> && // 当仅传入单个参数时,该参数不能是可转换为std::size_t的整数类型 (!(sizeof...(Elements) == 1 && std::integral<std::decay_t<Elements>> && std::convertible_to<Elements, std::size_t>)) cArray(Elements&&... args) : data{std::forward<Elements>(args)...} {} }; // 测试用例 int main() { cArray<int> arr1(7); // 调用size_t构造,创建大小为7的空数组 cArray<int> arr2{7}; // 调用initializer_list构造,创建含单个元素7的数组 cArray<int> arr3(7, 8, 9); // 调用变参构造,创建含三个元素的数组 cArray<std::string> arr4("hi"); // 调用变参构造,创建含单个字符串元素的数组 }
核心概念要点
- 重载决议的匹配规则:C++重载决议中,精确匹配(无隐式转换)的优先级高于需要隐式转换的匹配。原问题中,
cArray<int>(7)的两个构造函数都可行:变参构造接受int是精确匹配,而std::size_t构造需要int到std::size_t的隐式转换,因此变参构造被优先选中。 - SFINAE与约束的精准过滤:通过给变参构造函数添加额外约束,排除掉“单个可转换为
std::size_t的整数参数”的场景,强制编译器在该场景下只能选择std::size_t构造函数。这里利用C++20的std::integral和std::convertible_to概念实现类型过滤。 - 初始化语义的区分:引入
std::initializer_list构造函数,明确区分“圆括号传大小”和“花括号传元素”的语义,符合C++的惯用初始化方式,同时避免歧义。
内容的提问来源于stack exchange,提问作者SKNB
相关产品推荐
相关产品推荐

