如何实现继承std::tuple的类像普通tuple一样支持隐式参数转换初始化?
问题描述
原生std::tuple支持如下的隐式转换:
std::tuple< std::wstring, int64_t > item(L"str", 10); std::tuple< const std::wstring&, int64_t > item_ref = item;
这里std::wstring可以自动转换为const std::wstring&,完成引用绑定。
但当自定义一个继承自std::tuple的Identifier类后:
template< typename ... Args > class Identifier: public std::tuple< Args... > { public: Identifier( Args... args ):std::tuple< Args... >( std::forward< Args >( args )... ) {} Identifier( std::tuple< Args... > tuple ):std::tuple< Args... >( tuple ) {} };
尝试进行类似的转换时:
Identifier<std::wstring, int64_t> item(L"str", 10); Identifier<const std::wstring&, int64_t> item_ref = item;
会触发编译错误:
No viable conversion from 'Identifier<std::wstring, [...]>' to 'Identifier<const std::wstring &, [...]>'
解决方案
要实现这种兼容转换,需要给Identifier类添加模板构造函数,借助基类std::tuple本身的转换能力来完成类型适配。修改后的代码如下:
template< typename ... Args > class Identifier: public std::tuple< Args... > { public: // 原有构造函数 Identifier( Args... args ):std::tuple< Args... >( std::forward< Args >( args )... ) {} Identifier( std::tuple< Args... > tuple ):std::tuple< Args... >( tuple ) {} // 新增:支持从其他参数类型的Identifier转换 template<typename... OtherArgs> Identifier(const Identifier<OtherArgs...>& other) : std::tuple<Args...>(static_cast<const std::tuple<OtherArgs...>&>(other)) {} // 新增:直接兼容std::tuple的转换 template<typename... OtherArgs> Identifier(const std::tuple<OtherArgs...>& tuple) : std::tuple<Args...>(tuple) {} };
关键说明
std::tuple的隐式转换能力来自其内部的模板构造函数,而自定义类不会自动继承这类模板构造函数,必须手动添加。- 新增的第一个模板构造函数接受任意模板参数的
Identifier实例,将其转换为基类std::tuple后,利用基类的转换逻辑完成初始化。 - 第二个新增构造函数直接兼容
std::tuple类型,进一步扩展了Identifier的适配场景。
修改完成后,原有的转换代码即可正常编译,实现和原生std::tuple一致的引用绑定效果。
内容的提问来源于stack exchange,提问作者Vladimir Shttl
相关产品推荐
相关产品推荐

