如何在C++17中禁用泛化转发构造函数并沿用拷贝构造函数
解决方案
在C17环境下,可以通过std::enable_if_t结合折叠表达式替代C20的requires约束,既保留原构造函数的功能,又避免隐藏拷贝构造函数,同时不需要标记构造函数为explicit。
修改后的类实现代码如下:
#include <array> #include <type_traits> template <class T, int N> struct MyVec { std::array<T, N> m_vec; // 用C++17的enable_if替代C++20的requires约束 template <typename... Q, std::enable_if_t<(std::is_same_v<Q, T> && ...), int> = 0> MyVec(Q&&... args) : m_vec{std::forward<Q>(args)...} {} };
原使用示例可正常编译运行:
int main(int argc, char* argv[]) { using V = MyVec<double, 2>; V v0(1., 2.); V v1(1., 2.); V v2 = v0; // 现在可正常编译,不会被模板构造函数干扰 }
原理说明
- 约束参数类型:通过折叠表达式
(std::is_same_v<Q, T> && ...)确保所有传入的参数类型Q都与容器元素类型T完全一致,与原C++20requires约束效果等价。 - 避免隐藏拷贝构造:执行拷贝构造(如
V v2 = v0)时,编译器尝试匹配模板构造函数,但此时参数类型为MyVec<T, N>&,与T类型不匹配,std::enable_if_t条件不成立,该模板构造函数会被SFINAE机制排除。编译器会自动选择默认生成的拷贝构造函数,保证代码正常编译。 - 保留隐式构造:构造函数未标记
explicit,可支持符合条件的隐式初始化,满足需求。
内容的提问来源于stack exchange,提问作者bradgonesurfing
相关产品推荐
相关产品推荐

