代码之家  ›  专栏  ›  技术社区  ›  NeomerArcana

为什么在这里使用int64_t错误并编译int?

  •  1
  • NeomerArcana  · 技术社区  · 6 年前

    帮帮一个兄弟。这段代码编译,做我想做的。

    #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 (不是“附加”,而是“代替”),即 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> > >}'|
    

    我认为这很重要,因为我在任何时候都不会使用 利息 ,我正在使用 国际贸易组织 因此,程序似乎隐式地从 国际贸易组织 降到一个 利息 我不知道在哪里,为什么,如何阻止它。

    使用mingW64 7.3.0编译。

    2 回复  |  直到 6 年前
        1
  •  2
  •   1201ProgramAlarm    6 年前

    问题出在返回语句中 BinaryOp::GetValue 功能。第一个错误来自 return a + b; 线,展开时 bool 变量的成员。这两个bool值被转换为 int ,将它们相加,然后使用该int创建新的 GlobalVariables::VariableType 值。但是,没有明确的转换来自 利息 VariableType .

    其他错误都来自于 return 0; 出于同样的原因。

    修复非常简单。更改第一个 return

    return decltype(a)(a + b);
    

    将加法结果转换为与 a ,这对于提升到 利息 在添加之前( 布尔 ,请 char ,请 short 以及它们的有符号/无符号变体)。

    对于 返回0; 行,您需要决定 0 应该是(bool?国际64?浮动?)并显式指定该0的类型。

        2
  •  0
  •   AnT stands with Russia    6 年前

    转换为您的 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 显然是最好的候选人,因为它不需要从 利息 .一旦你换了 利息 具有 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 
    

    错误。