如何让IdentifierType的std::is_default_constructible结果与tuple一致?
问题描述
我定义了一个继承自std::tuple的模板类IdentifierType,尝试用std::is_default_constructible检查其默认构造能力,代码如下:
template<typename ... Args> class IdentifierType: public std::tuple<Args...> { public: IdentifierType(Args... args) requires( sizeof...(Args) != 0 ) :std::tuple<Args...>( std::move(args)... ) {} IdentifierType(std::tuple<Args...> tuple ):std::tuple<Args...>( std::move(tuple) ) {} IdentifierType() {} IdentifierType(const IdentifierType&) = default; IdentifierType(IdentifierType&&) = default; IdentifierType& operator=(const IdentifierType& other) = default; IdentifierType& operator=(IdentifierType&& other) = default; IdentifierType(std::convertible_to<std::tuple<Args...>> auto&& identifier ) : std::tuple<Args...>( std::forward<decltype(identifier)>(identifier) ) {} }; struct Reader { int mId; Reader(int id):mId(id) {} }; int main() { std::cout << "Reader: " << std::is_default_constructible<Reader>::value << std::endl; std::cout << "tuple Reader: " << std::is_default_constructible<std::tuple<Reader>>::value << std::endl; std::cout << "IdentifierType Reader: " << std::is_default_constructible<IdentifierType<Reader>>::value << std::endl; }
程序输出:
Reader: false tuple Reader: false IdentifierType Reader: true
最后一行输出为true是因为IdentifierType显式定义了默认构造函数。请问需要修改哪些地方,才能让std::is_default_constructible<IdentifierType>::value的结果与std::tuple的结果一致?
解决方案
要让IdentifierType的默认构造能力与std::tuple保持一致,只需修改默认构造函数的定义:
- 删除显式定义的空体默认构造函数:移除代码中的
IdentifierType() {}这一行。 - 添加默认生成的默认构造函数:替换为
IdentifierType() = default;。
修改后的IdentifierType类核心部分如下:
template<typename ... Args> class IdentifierType: public std::tuple<Args...> { public: IdentifierType(Args... args) requires( sizeof...(Args) != 0 ) :std::tuple<Args...>( std::move(args)... ) {} IdentifierType(std::tuple<Args...> tuple ):std::tuple<Args...>( std::move(tuple) ) {} IdentifierType() = default; // 替换原空体默认构造函数 IdentifierType(const IdentifierType&) = default; IdentifierType(IdentifierType&&) = default; IdentifierType& operator=(const IdentifierType& other) = default; IdentifierType& operator=(IdentifierType&& other) = default; IdentifierType(std::convertible_to<std::tuple<Args...>> auto&& identifier ) : std::tuple<Args...>( std::forward<decltype(identifier)>(identifier) ) {} };
原理说明
- 原代码中显式写的空体默认构造函数
IdentifierType() {}会强制类拥有一个默认构造入口,即便基类std::tuple<Args...>无法默认构造,std::is_default_constructible也会返回true,但实际调用这个构造函数会触发编译错误。 - 使用
= default声明后,编译器会自动生成与基类行为绑定的默认构造逻辑:- 当
std::tuple<Args...>支持默认构造(所有模板参数都能默认构造)时,IdentifierType的默认构造函数正常可用,std::is_default_constructible返回true; - 当
std::tuple<Args...>不支持默认构造时,IdentifierType的默认构造函数会被编译器隐式删除,此时std::is_default_constructible返回false,完全匹配std::tuple的结果。
- 当
内容的提问来源于stack exchange,提问作者Vladimir Shttl
相关产品推荐
相关产品推荐

