此boost-variant-ambiguous-construction question已触及该主题。
但我的问题不在于可以相互转换的类型,而是与完全不相关的类型。
简化示例:
// types not related in any way
class A {};
class B {};
class C {};
class D {};
using ABC_variant = boost::variant<A,B,C>;
using D_optional = boost::optional<D>;
该问题与某些类型的可选项不可打印的事实有关。但是,对于某些变体,完全不相关的输出运算符试图接受此boost :: optional类型(D_optional)。
请参阅:
std::ostream& operator << (std::ostream& os, const ABC_variant&)
{
return os << "ABC";
}
int main() {
D_optional dopt;
std::cout << dopt;
}
您可以在ideone上看到 - 很多编译器错误说它不知道您要打印bool
或ABC_variant
的内容以及ABC_variant
的情况不知道如何将D_optional
转换为ABC_variant
。据我所知,boost :: optional可转换为bool
,第一种选择是正确的我不知道为什么它会尝试使用ABC_variant
转换......
此外,我更简化了这个例子并放弃了boost :: optional:
int main() {
D d;
std::cout << d;
}
现在,它没有“bool
替代”,只是抱怨它试图从ABC_variant
构建D
:
prog.cpp:23:15:从这里要求 /usr/include/boost/variant/variant.hpp:1591:38:错误:没有匹配 调用'boost :: variant :: initializer :: initialize(void *,D&amp;)'的函数 初始化初始化::(
此此处是ABC_variant
的ostream运算符。
当然我知道为D / D_opt编写ostream运算符将解决问题 - 但问题在于诊断:如果boost :: variant不接受任何类型作为其构造函数的参数,编译器会告诉我简单的true - 不是这一堆误导性的句子......
我怀疑它是以这种方式设计 - 也许正在进行一些修复?
幸运的是我和ideone使用相同的编译器和boost:gcc4.9和boost1.58。
答案 0 :(得分:1)
我创建了boost ticket for this problem。只是为了澄清什么是真正的问题:
真正的问题在于此boost.variant&#34;转换&#34;构造函数接受任何类型 - 没有限制,即使如此自然,如该参数类型应该可以转换为任何此boost.variant实例化类型:
template <typename T>
variant(const T& operand)
{
convert_construct(operand, 1L);
}
我建议的解决方案可能是这样的:
template <typename T, typename ...C>
struct IsAnyOf;
template <typename T, typename ...C>
struct IsAnyOf<T,T,C...> : std::true_type {};
template <typename T>
struct IsAnyOf<T> : std::false_type {};
template <typename T, typename C1, typename ...C>
struct IsAnyOf<T,C1,C...> : IsAnyOf<T, C...> {};
template <typename T,
typename EnableIf = typename std::enable_if<IsAnyOf<VariantType...>::value>::type>
variant(const T& operand)
但是现在 - 唯一的解决方案是不创建任何接受boost :: variant实例化的非模板函数。因此要么在某些结构类型中创建函数模板或者boost :: variant的聚合实例化。
所以要么:
template <typename T>
typename std::enable_if<std::is_same<T,ABC_variant>::value, std::ostream&>::type
operator << (std::ostream& os, const T&)
{
return os << "ABC";
}
或类似的东西:
struct ABC_variant
{
boost::variant<A,B,C> v;
ABC_variant(const A&);
ABC_variant(const B&);
ABC_variant(const C&);
};
issue已在boots.1.62
中修复