std::variant 隔离包含类型时的模板推导
std::variant template deduction when isolating containing type
我今天一直在制作序列化器,但在使用变体时遇到了问题。
我之前用这个过程来处理其他各种事情,我不断地修剪类型,直到我得到我需要的一种类型。不过这次好像VC++推不出来
这是错误的完整示例。
#include <type_traits>
#include <variant>
#include <iostream>
#include <sstream>
void serialize( auto& s, float v ) {
std::cout << "serialize float";
}
void serialize( auto& s, int v ) {
std::cout << "serialize int";
}
void serialize( auto& s, bool v ) {
std::cout << "serialize bool";
}
namespace detail
{
template<typename VariantT, typename T1, typename ...Rest>
void serialize_variant( auto& s, const VariantT& v ) {
if ( std::holds_alternative<T1>( v ) )
return serialize( s, std::get<T1>( v ) );
else if ( sizeof...(Rest) >= 1 )
return serialize_variant<VariantT, Rest...>( s, v );
else return;
}
}
template<typename ...VariantTs>
void serialize( auto& s, const std::variant<VariantTs...>& v ) {
detail::serialize_variant<std::variant<VariantTs...>, VariantTs...>( s, v );
}
int main() {
std::stringstream s{};
std::variant<float, int, bool> x = true;
serialize( s, x );
}
我很困惑为什么这不起作用。它应该检查 T1 是否是变体包含的类型。如果不是,则它会检查是否有更多类型要检查,并在存在时用更少的类型调用相同的 serialize_variant 函数,否则它只是 returns。它在递归调用中为 serialize_variant 抛出一个不匹配的重载,它说它不能推断出 T1.
谁能解释一下编译失败的原因?
我得到的是以下错误
Error C2672 'serialize_variant': no matching overloaded function found
Error C2783 'void detail::serialize_variant(_T0 &,const VariantT &)': could not deduce
template argument for 'T1'
谢谢。
带有sizeof...(Rest) >= 1
的分支在条件为false
时也必须有效,但事实并非如此。当条件为 false
时,您可以通过 if constexpr
将其丢弃。此外,无论您尝试 return 什么,但 return 类型是 void
。
namespace detail
{
template<typename VariantT, typename T1, typename ...Rest>
void serialize_variant( auto& s, const VariantT& v ) {
if ( std::holds_alternative<T1>( v ) )
/*return*/ serialize( s, std::get<T1>( v ) );
else {
if constexpr ( sizeof...(Rest) >= 1 )
/*return*/ serialize_variant<VariantT, Rest...>( s, v );
else return;
}
}
}
我今天一直在制作序列化器,但在使用变体时遇到了问题。
我之前用这个过程来处理其他各种事情,我不断地修剪类型,直到我得到我需要的一种类型。不过这次好像VC++推不出来
这是错误的完整示例。
#include <type_traits>
#include <variant>
#include <iostream>
#include <sstream>
void serialize( auto& s, float v ) {
std::cout << "serialize float";
}
void serialize( auto& s, int v ) {
std::cout << "serialize int";
}
void serialize( auto& s, bool v ) {
std::cout << "serialize bool";
}
namespace detail
{
template<typename VariantT, typename T1, typename ...Rest>
void serialize_variant( auto& s, const VariantT& v ) {
if ( std::holds_alternative<T1>( v ) )
return serialize( s, std::get<T1>( v ) );
else if ( sizeof...(Rest) >= 1 )
return serialize_variant<VariantT, Rest...>( s, v );
else return;
}
}
template<typename ...VariantTs>
void serialize( auto& s, const std::variant<VariantTs...>& v ) {
detail::serialize_variant<std::variant<VariantTs...>, VariantTs...>( s, v );
}
int main() {
std::stringstream s{};
std::variant<float, int, bool> x = true;
serialize( s, x );
}
我很困惑为什么这不起作用。它应该检查 T1 是否是变体包含的类型。如果不是,则它会检查是否有更多类型要检查,并在存在时用更少的类型调用相同的 serialize_variant 函数,否则它只是 returns。它在递归调用中为 serialize_variant 抛出一个不匹配的重载,它说它不能推断出 T1.
谁能解释一下编译失败的原因?
我得到的是以下错误
Error C2672 'serialize_variant': no matching overloaded function found
Error C2783 'void detail::serialize_variant(_T0 &,const VariantT &)': could not deduce
template argument for 'T1'
谢谢。
带有sizeof...(Rest) >= 1
的分支在条件为false
时也必须有效,但事实并非如此。当条件为 false
时,您可以通过 if constexpr
将其丢弃。此外,无论您尝试 return 什么,但 return 类型是 void
。
namespace detail
{
template<typename VariantT, typename T1, typename ...Rest>
void serialize_variant( auto& s, const VariantT& v ) {
if ( std::holds_alternative<T1>( v ) )
/*return*/ serialize( s, std::get<T1>( v ) );
else {
if constexpr ( sizeof...(Rest) >= 1 )
/*return*/ serialize_variant<VariantT, Rest...>( s, v );
else return;
}
}
}