为什么在这里使用 int64_t 错误和 int 编译?
Why does using a int64_t error here and an int compiles?
帮帮小弟。这段代码编译,做我想要的。
#include <iostream>
#include <unordered_map>
#include <variant>
#include <vector>
#include <random>
#include <ctime>
class GlobalVariables
{
public:
typedef std::wstring VariableNameType;
/***************************************************************
----------------------------------------------------------------------
Important that my std::variant holds an int
-----------------------------------------------------------------
*****************************************************************/
typedef std::variant<bool,int,float,std::wstring> VariableType;
typedef std::unordered_map<VariableNameType,VariableType> VariableContainerType;
static const VariableType& GetValue(const VariableNameType& name) { return m_variables[name]; }
static void SetValue(const VariableNameType& name, const VariableType value) { m_variables[name] = value; }
protected:
static VariableContainerType m_variables;
};
GlobalVariables::VariableContainerType GlobalVariables::m_variables;
class RandomNumber
{
public:
typedef std::mt19937 EngineType;
static void Seed(const EngineType::result_type seed)
{
m_engine.seed(seed);
}
protected:
static EngineType m_engine;
};
RandomNumber::EngineType RandomNumber::m_engine(std::time(0));
template<typename T>
class RandomNumberGenerator : public RandomNumber
{ };
template<>
class RandomNumberGenerator<int> : public RandomNumber
{
public:
RandomNumberGenerator(const int min, const int max)
:
m_intDistro(min,max)
{}
int operator()() { return m_intDistro(m_engine); }
protected:
std::uniform_int_distribution<int> m_intDistro;
};
template<>
class RandomNumberGenerator<float> : public RandomNumber
{
public:
RandomNumberGenerator(const float min, const float max)
:
m_floatDistro(min,max)
{}
float operator()() { return m_floatDistro(m_engine); }
protected:
std::uniform_real_distribution<float> m_floatDistro;
};
enum class COMPARISON_OP : uint8_t { EE, NE, LT, GT, LE, GE };
enum class BINARY_OP : uint8_t { ADD, SUB, MUL, DIV };
class Expression
{
public:
virtual GlobalVariables::VariableType GetValue() const = 0;
};
class Constant : public Expression
{
public:
virtual GlobalVariables::VariableType GetValue() const
{
return value;
}
GlobalVariables::VariableType value;
};
class Identifier : public Expression
{
public:
virtual GlobalVariables::VariableType GetValue() const override
{
return GlobalVariables::GetValue(name);
}
GlobalVariables::VariableNameType name;
};
class System : public Expression
{
public:
virtual GlobalVariables::VariableType GetValue() const override
{
return GlobalVariables::GetValue(name);
}
GlobalVariables::VariableNameType name;
};
class BinaryOp : public Expression
{
public:
virtual GlobalVariables::VariableType GetValue() const override
{
if(op == BINARY_OP::ADD)
/***************************************************************
----------------------------------------------------------------------
Important that my visitor returns a simple addition if the types are the
same
-----------------------------------------------------------------
*****************************************************************/
return std::visit([](auto a, auto b) -> GlobalVariables::VariableType
{
if constexpr(!std::is_same_v<decltype(a),decltype(b)>)
throw;
else
return a + b;
}, lhs->GetValue(), rhs->GetValue());
else if(op == BINARY_OP::SUB)
return 0;
else if(op == BINARY_OP::MUL)
return 0;
else // Division
return 0;
}
BINARY_OP op;
Expression* lhs;
Expression* rhs;
};
class Comparison
{
public:
bool GetValue() const
{
if(op == COMPARISON_OP::EE)
return lhs->GetValue() == rhs->GetValue();
else if(op == COMPARISON_OP::NE)
return lhs->GetValue() != rhs->GetValue();
else if(op == COMPARISON_OP::LT)
return lhs->GetValue() < rhs->GetValue();
else if(op == COMPARISON_OP::GT)
return lhs->GetValue() > rhs->GetValue();
else if(op == COMPARISON_OP::LE)
return lhs->GetValue() <= rhs->GetValue();
else // Greater or Equal to
return lhs->GetValue() >= rhs->GetValue();
}
COMPARISON_OP op;
Expression* lhs;
Expression* rhs;
};
class Random : public Expression
{
public:
virtual GlobalVariables::VariableType GetValue() const override
{
return possibilities[randomSelector()]->GetValue();
}
mutable RandomNumberGenerator<int> randomSelector;
std::vector<Expression*> possibilities;
};
class Option
{
};
class Event
{
public:
Expression* eventText;
};
class Branch
{
public:
const std::wstring& GetValue() const
{
if(condition->GetValue())
return trueBody;
else
return falseBody;
}
Comparison* condition;
std::wstring trueBody;
std::wstring falseBody;
};
int main()
{
}
可能有很多不必要的代码,所以我突出显示了我认为重要的部分。
但是,如果我将 std::variant
更改为保持 int64_t
而不是 int
(不是 "in addition to",而是 "instead of"),即 typedef std::variant<bool,int64_t,float,std::wstring> VariableType
程序编译失败。
编译错误很长:
||=== Build: Debug in Space Adventure 2 (compiler: Mingw-7.3.0) ===|
main.cpp||In instantiation of 'BinaryOp::GetValue() const::<lambda(auto:1, auto:2)> [with auto:1 = bool; auto:2 = bool; GlobalVariables::VariableType = std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >]':|
\include\c++\type_traits|2797|required from 'constexpr bool std::__call_is_nt(std::__invoke_other) [with _Fn = BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>; _Args = {bool, bool}]'|
\include\c++\type_traits|2803| required by substitution of 'template<bool __v> using __bool_constant = std::integral_constant<bool, __v> [with bool __v = std::__call_is_nt<BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>, bool, bool>((std::__result_of_success<std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >, std::__invoke_other>::__invoke_type{}, std::__result_of_success<std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, st|
\include\c++\type_traits|2801|required from 'struct std::__call_is_nothrow<std::__invoke_result<BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>, bool, bool>, BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>, bool, bool>'|
\include\c++\type_traits|143|required from 'struct std::__and_<std::__is_invocable<BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>, bool, bool>, std::__call_is_nothrow<std::__invoke_result<BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>, bool, bool>, BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>, bool, bool> >'|
\include\c++\type_traits|2813|required from 'struct std::__is_nothrow_invocable<BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>, bool, bool>'|
\include\c++\bits\invoke.h|89| [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]|
\include\c++\variant|691|required from 'static constexpr auto std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...)>, std::tuple<_Tail ...>, std::integer_sequence<long long unsigned int, __indices ...> >::_S_apply() [with _Result_type = std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >; _Visitor = BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>&&; _Variants = {std::variant<bo|
\include\c++\variant|656| recursively required from 'static constexpr void std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long long unsigned int, __indices ...> >::_S_apply_single_alt(_Tp&) [with long long unsigned int __index = 0; _Tp = std::__detail::__variant::_Multi_array<std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::al|
\include\c++\variant|656|required from 'constexpr const std::__detail::__variant::_Multi_array<std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > (*)(BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::alloc|
\include\c++\variant|709|required from 'struct std::__detail::__variant::__gen_vtable<std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >, BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t|
\include\c++\variant|1245|required from 'constexpr decltype(auto) std::visit(_Visitor&&, _Variants&& ...) [with _Visitor = BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>; _Variants = {std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >}]'|
main.cpp|133|required from here|
\include\c++\variant|709| in constexpr expansion of 'std::__detail::__variant::__gen_vtable<std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >, BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<|
\include\c++\variant|706| in constexpr expansion of 'std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > (*)(BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wcha|
\include\c++\variant|646| in constexpr expansion of 'std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > (*)(BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wcha|
\include\c++\variant|668| in constexpr expansion of 'std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > (*)(BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wcha|
\include\c++\variant|646| in constexpr expansion of 'std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > (*)(BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wcha|
main.cpp|132|error: could not convert '(((int)a) + ((int)b))' from 'int' to 'GlobalVariables::VariableType {aka std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >}'|
main.cpp||In member function 'virtual GlobalVariables::VariableType BinaryOp::GetValue() const':|
main.cpp|135|error: could not convert '0' from 'int' to 'GlobalVariables::VariableType {aka std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >}'|
main.cpp|137|error: could not convert '0' from 'int' to 'GlobalVariables::VariableType {aka std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >}'|
main.cpp|139|error: could not convert '0' from 'int' to 'GlobalVariables::VariableType {aka std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >}'|
||=== Build failed: 12 error(s), 10 warning(s) (0 minute(s), 1 second(s)) ===|
但我认为真正的关键是这个错误:
\main.cpp|132|error: could not convert '(((int)a) + ((int)b))' from 'int' to 'GlobalVariables::VariableType {aka std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >}'|
我认为这很重要,因为我在任何时候都没有使用 int
,我使用的是 int64_t
,所以程序似乎已经从 int64_t
隐式转换为一个 int
,我不知道在哪里、为什么或如何停止它。
使用 Mingw64 7.3.0 编译。
您的 VariableType
变体的转换不明确。你可以用你的一组类型做一个简单的测试
#include <cstdint>
#include <string>
void foo(bool);
void foo(int64_t);
void foo(float);
void foo(std::wstring);
int main()
{
foo(0);
}
此代码将无法编译,因为对 foo
的重载调用不明确:有许多候选对象可以通过隐式转换调用,但没有一个是最好的。在构造 std::variant
时实际上采用了相同的逻辑(参见构造函数 4 here 的描述)。
在您的原始版本中,int
显然是最佳候选,因为它不需要从 int
进行转换。将 int
替换为 int64_t
后,所有类型都需要转换并且没有赢家。这就是
的原因
error: could not convert '0' from 'int' to 'GlobalVariables::VariableType
错误以及
error: could not convert '(((int)a) + ((int)b))' from 'int' to 'GlobalVariables::VariableType
错误。
问题出在 BinaryOp::GetValue
函数中的 return 语句。第一个错误来自 return a + b;
行,当扩展变体的 bool
成员时。两个 bool 值被转换为 int
,它们被加在一起,然后那个 int 被用来创建一个新的 GlobalVariables::VariableType
值。但是,没有从 int
到 VariableType
.
的明确转换
出于同样的原因,其他错误都来自各种 return 0;
语句。
修复非常简单。将第一个return
改为
return decltype(a)(a + b);
这会将加法的结果转换为与 a
相同的类型,这对于在加法发生之前提升为 int
的小类型是必需的(bool
, char
、short
及其 signed/unsigned 变体)。
对于 return 0;
行,您需要确定 0
应该是什么类型(bool?int_64?float?)并明确指定该 0 的类型。
帮帮小弟。这段代码编译,做我想要的。
#include <iostream>
#include <unordered_map>
#include <variant>
#include <vector>
#include <random>
#include <ctime>
class GlobalVariables
{
public:
typedef std::wstring VariableNameType;
/***************************************************************
----------------------------------------------------------------------
Important that my std::variant holds an int
-----------------------------------------------------------------
*****************************************************************/
typedef std::variant<bool,int,float,std::wstring> VariableType;
typedef std::unordered_map<VariableNameType,VariableType> VariableContainerType;
static const VariableType& GetValue(const VariableNameType& name) { return m_variables[name]; }
static void SetValue(const VariableNameType& name, const VariableType value) { m_variables[name] = value; }
protected:
static VariableContainerType m_variables;
};
GlobalVariables::VariableContainerType GlobalVariables::m_variables;
class RandomNumber
{
public:
typedef std::mt19937 EngineType;
static void Seed(const EngineType::result_type seed)
{
m_engine.seed(seed);
}
protected:
static EngineType m_engine;
};
RandomNumber::EngineType RandomNumber::m_engine(std::time(0));
template<typename T>
class RandomNumberGenerator : public RandomNumber
{ };
template<>
class RandomNumberGenerator<int> : public RandomNumber
{
public:
RandomNumberGenerator(const int min, const int max)
:
m_intDistro(min,max)
{}
int operator()() { return m_intDistro(m_engine); }
protected:
std::uniform_int_distribution<int> m_intDistro;
};
template<>
class RandomNumberGenerator<float> : public RandomNumber
{
public:
RandomNumberGenerator(const float min, const float max)
:
m_floatDistro(min,max)
{}
float operator()() { return m_floatDistro(m_engine); }
protected:
std::uniform_real_distribution<float> m_floatDistro;
};
enum class COMPARISON_OP : uint8_t { EE, NE, LT, GT, LE, GE };
enum class BINARY_OP : uint8_t { ADD, SUB, MUL, DIV };
class Expression
{
public:
virtual GlobalVariables::VariableType GetValue() const = 0;
};
class Constant : public Expression
{
public:
virtual GlobalVariables::VariableType GetValue() const
{
return value;
}
GlobalVariables::VariableType value;
};
class Identifier : public Expression
{
public:
virtual GlobalVariables::VariableType GetValue() const override
{
return GlobalVariables::GetValue(name);
}
GlobalVariables::VariableNameType name;
};
class System : public Expression
{
public:
virtual GlobalVariables::VariableType GetValue() const override
{
return GlobalVariables::GetValue(name);
}
GlobalVariables::VariableNameType name;
};
class BinaryOp : public Expression
{
public:
virtual GlobalVariables::VariableType GetValue() const override
{
if(op == BINARY_OP::ADD)
/***************************************************************
----------------------------------------------------------------------
Important that my visitor returns a simple addition if the types are the
same
-----------------------------------------------------------------
*****************************************************************/
return std::visit([](auto a, auto b) -> GlobalVariables::VariableType
{
if constexpr(!std::is_same_v<decltype(a),decltype(b)>)
throw;
else
return a + b;
}, lhs->GetValue(), rhs->GetValue());
else if(op == BINARY_OP::SUB)
return 0;
else if(op == BINARY_OP::MUL)
return 0;
else // Division
return 0;
}
BINARY_OP op;
Expression* lhs;
Expression* rhs;
};
class Comparison
{
public:
bool GetValue() const
{
if(op == COMPARISON_OP::EE)
return lhs->GetValue() == rhs->GetValue();
else if(op == COMPARISON_OP::NE)
return lhs->GetValue() != rhs->GetValue();
else if(op == COMPARISON_OP::LT)
return lhs->GetValue() < rhs->GetValue();
else if(op == COMPARISON_OP::GT)
return lhs->GetValue() > rhs->GetValue();
else if(op == COMPARISON_OP::LE)
return lhs->GetValue() <= rhs->GetValue();
else // Greater or Equal to
return lhs->GetValue() >= rhs->GetValue();
}
COMPARISON_OP op;
Expression* lhs;
Expression* rhs;
};
class Random : public Expression
{
public:
virtual GlobalVariables::VariableType GetValue() const override
{
return possibilities[randomSelector()]->GetValue();
}
mutable RandomNumberGenerator<int> randomSelector;
std::vector<Expression*> possibilities;
};
class Option
{
};
class Event
{
public:
Expression* eventText;
};
class Branch
{
public:
const std::wstring& GetValue() const
{
if(condition->GetValue())
return trueBody;
else
return falseBody;
}
Comparison* condition;
std::wstring trueBody;
std::wstring falseBody;
};
int main()
{
}
可能有很多不必要的代码,所以我突出显示了我认为重要的部分。
但是,如果我将 std::variant
更改为保持 int64_t
而不是 int
(不是 "in addition to",而是 "instead of"),即 typedef std::variant<bool,int64_t,float,std::wstring> VariableType
程序编译失败。
编译错误很长:
||=== Build: Debug in Space Adventure 2 (compiler: Mingw-7.3.0) ===|
main.cpp||In instantiation of 'BinaryOp::GetValue() const::<lambda(auto:1, auto:2)> [with auto:1 = bool; auto:2 = bool; GlobalVariables::VariableType = std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >]':|
\include\c++\type_traits|2797|required from 'constexpr bool std::__call_is_nt(std::__invoke_other) [with _Fn = BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>; _Args = {bool, bool}]'|
\include\c++\type_traits|2803| required by substitution of 'template<bool __v> using __bool_constant = std::integral_constant<bool, __v> [with bool __v = std::__call_is_nt<BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>, bool, bool>((std::__result_of_success<std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >, std::__invoke_other>::__invoke_type{}, std::__result_of_success<std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, st|
\include\c++\type_traits|2801|required from 'struct std::__call_is_nothrow<std::__invoke_result<BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>, bool, bool>, BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>, bool, bool>'|
\include\c++\type_traits|143|required from 'struct std::__and_<std::__is_invocable<BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>, bool, bool>, std::__call_is_nothrow<std::__invoke_result<BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>, bool, bool>, BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>, bool, bool> >'|
\include\c++\type_traits|2813|required from 'struct std::__is_nothrow_invocable<BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>, bool, bool>'|
\include\c++\bits\invoke.h|89| [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]|
\include\c++\variant|691|required from 'static constexpr auto std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...)>, std::tuple<_Tail ...>, std::integer_sequence<long long unsigned int, __indices ...> >::_S_apply() [with _Result_type = std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >; _Visitor = BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>&&; _Variants = {std::variant<bo|
\include\c++\variant|656| recursively required from 'static constexpr void std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long long unsigned int, __indices ...> >::_S_apply_single_alt(_Tp&) [with long long unsigned int __index = 0; _Tp = std::__detail::__variant::_Multi_array<std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::al|
\include\c++\variant|656|required from 'constexpr const std::__detail::__variant::_Multi_array<std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > (*)(BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::alloc|
\include\c++\variant|709|required from 'struct std::__detail::__variant::__gen_vtable<std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >, BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t|
\include\c++\variant|1245|required from 'constexpr decltype(auto) std::visit(_Visitor&&, _Variants&& ...) [with _Visitor = BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>; _Variants = {std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >}]'|
main.cpp|133|required from here|
\include\c++\variant|709| in constexpr expansion of 'std::__detail::__variant::__gen_vtable<std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >, BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<|
\include\c++\variant|706| in constexpr expansion of 'std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > (*)(BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wcha|
\include\c++\variant|646| in constexpr expansion of 'std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > (*)(BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wcha|
\include\c++\variant|668| in constexpr expansion of 'std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > (*)(BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wcha|
\include\c++\variant|646| in constexpr expansion of 'std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > (*)(BinaryOp::GetValue() const::<lambda(auto:1, auto:2)>&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >&&, std::variant<bool, long long int, float, std::__cxx11::basic_string<wcha|
main.cpp|132|error: could not convert '(((int)a) + ((int)b))' from 'int' to 'GlobalVariables::VariableType {aka std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >}'|
main.cpp||In member function 'virtual GlobalVariables::VariableType BinaryOp::GetValue() const':|
main.cpp|135|error: could not convert '0' from 'int' to 'GlobalVariables::VariableType {aka std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >}'|
main.cpp|137|error: could not convert '0' from 'int' to 'GlobalVariables::VariableType {aka std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >}'|
main.cpp|139|error: could not convert '0' from 'int' to 'GlobalVariables::VariableType {aka std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >}'|
||=== Build failed: 12 error(s), 10 warning(s) (0 minute(s), 1 second(s)) ===|
但我认为真正的关键是这个错误:
\main.cpp|132|error: could not convert '(((int)a) + ((int)b))' from 'int' to 'GlobalVariables::VariableType {aka std::variant<bool, long long int, float, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >}'|
我认为这很重要,因为我在任何时候都没有使用 int
,我使用的是 int64_t
,所以程序似乎已经从 int64_t
隐式转换为一个 int
,我不知道在哪里、为什么或如何停止它。
使用 Mingw64 7.3.0 编译。
您的 VariableType
变体的转换不明确。你可以用你的一组类型做一个简单的测试
#include <cstdint>
#include <string>
void foo(bool);
void foo(int64_t);
void foo(float);
void foo(std::wstring);
int main()
{
foo(0);
}
此代码将无法编译,因为对 foo
的重载调用不明确:有许多候选对象可以通过隐式转换调用,但没有一个是最好的。在构造 std::variant
时实际上采用了相同的逻辑(参见构造函数 4 here 的描述)。
在您的原始版本中,int
显然是最佳候选,因为它不需要从 int
进行转换。将 int
替换为 int64_t
后,所有类型都需要转换并且没有赢家。这就是
error: could not convert '0' from 'int' to 'GlobalVariables::VariableType
错误以及
error: could not convert '(((int)a) + ((int)b))' from 'int' to 'GlobalVariables::VariableType
错误。
问题出在 BinaryOp::GetValue
函数中的 return 语句。第一个错误来自 return a + b;
行,当扩展变体的 bool
成员时。两个 bool 值被转换为 int
,它们被加在一起,然后那个 int 被用来创建一个新的 GlobalVariables::VariableType
值。但是,没有从 int
到 VariableType
.
出于同样的原因,其他错误都来自各种 return 0;
语句。
修复非常简单。将第一个return
改为
return decltype(a)(a + b);
这会将加法的结果转换为与 a
相同的类型,这对于在加法发生之前提升为 int
的小类型是必需的(bool
, char
、short
及其 signed/unsigned 变体)。
对于 return 0;
行,您需要确定 0
应该是什么类型(bool?int_64?float?)并明确指定该 0 的类型。