【问题标题】:Type inference in Visual C++ 2008Visual C++ 2008 中的类型推断
【发布时间】:2010-11-27 14:20:50
【问题描述】:

Microsoft Visual C++ 2008 中是否有一些特定于供应商的类型推断机制,类似于 C++0x 中的标准化 autodecltype

【问题讨论】:

    标签: c++ visual-c++ c++11 type-inference decltype


    【解决方案1】:

    不,不是这样的,标准的、供应商特定的或插件。你必须升级到 VS2010,它实现了 auto

    【讨论】:

    • 如果您现在需要Visual C++ 2010 编译器,可以下载the Windows SDK
    • +1:您必须升级到 VS2010 才能使用 auto 或 decltype 或等效项——没有 GCC 样式的 typeof()。 Express 版当然是免费的,但其他版本不是。
    【解决方案2】:

    引用 Arkadiy Vertleyb 的 Boost mailing list 文章:

    只有上帝知道还能找到什么 如果愿意的话,在这个编译器里面 深入挖掘。

    例如,来自 RSDN 的 Igor' Chesnokov (俄罗斯软件开发网) 找到了实现 typeof() 的方法 不需要注册, 并且可能有编译时间 原生 typeof 的性能。

    怎么样?显然,一些奇怪的“功能” Visual C++ 允许他 模板正文 实例化,当附加上下文 可用,因此“注册” 即时上课,此刻 采用 typeof()。

    微软特有的“bugfeatures”是 一般不在我的范围内 利益。然而我确实意识到, 在 Microsoft 编译器上,这可能 看起来更有吸引力 佩德和我已经实施的任何事情。 即使我意识到这 可能是一场严肃的比赛,我 更不用说会感觉很糟糕 这里:

    http://rsdn.ru/Forum/?mid=1094305

    并从上面引用的链接引用的页面中引用 Igor Chesnokov 的代码:

    // type_of() evil implementation for VC7
    //
    // (c) Chez
    // mailto:chezu@pisem.net
    
    #include "stdafx.h"
    
    // This file contains:
    // 1) type_id(type)
    // 2) var_type_id(expersssion)
    // 3) type_of(expression)
    
    // IMPLEMENTATION
    template<int ID>
    class CTypeRegRoot
    {
    public:
        class id2type;
    };
    
    template<typename T, int ID>
    class CTypeReg : public CTypeRegRoot<ID>
    {
    public:
        class CTypeRegRoot<ID>::id2type // This uses nice VC6-VC7 bugfeature
        {
        public:
            typedef T Type;
        };
    
        typedef void Dummy;
    };
    
    template<int N>
    class CCounter;
    
    // TUnused is required to force compiler to recompile CCountOf class
    template<typename TUnused, int NTested = 0>
    class CCountOf
    {
    public:
        enum
        {
            __if_exists(CCounter<NTested>) { count = CCountOf<TUnused, NTested + 1>::count }
            __if_not_exists(CCounter<NTested>) { count = NTested }
        };
    };
    
    template<class TTypeReg, class TUnused, int NValue> // Helper class
    class CProvideCounterValue
    {
    public:
        enum { value = NValue };
    };
    
    // type_id
    #define type_id(type) \
        (CProvideCounterValue< \
            /*register TYPE--ID*/ typename CTypeReg<type, CCountOf<type >::count>::Dummy, \
            /*increment compile-time Counter*/ CCounter<CCountOf<type >::count>, \
            /*pass value of Counter*/CCountOf<type >::count \
         >::value)
    
    // Lets type_id() be > than 0
    class __Increment_type_id { enum { value = type_id(__Increment_type_id) }; };
    
    template<int NSize>
    class sized
    {
    private:
        char m_pad[NSize];
    };
    
    template<typename T>
    typename sized<type_id(T)> VarTypeID(T&);
    template<typename T>
    typename sized<type_id(const T)> VarTypeID(const T&);
    template<typename T>
    typename sized<type_id(volatile  T)> VarTypeID(volatile T&);
    template<typename T>
    typename sized<type_id(const volatile T)> VarTypeID(const volatile T&);
    
    // Unfortunatelly, var_type_id() does not recognize references
    #define var_type_id(var) \
        (sizeof(VarTypeID(var)))
    
    // type_of
    #define type_of(expression) \
        /* This uses nice VC6-VC7 bugfeature */ \
        CTypeRegRoot<var_type_id(expression)>::id2type::Type
    
    // auto_operator
    #define auto_operator(arg1, arg2, op) \
        type_of(instance(arg1) op instance(arg2)) operator op
    
    
    // TEST    
    class A
    {
    public:
        friend static const char* operator +(const A& a, const A& b)
        {
            return "chijik-pijik";
        }
    };
    
    template<typename T>
    class Plus
    {
    public:
        friend static type_of(T() + T()) operator +(const Plus<T>& a, const Plus<T>& b)
        {
            return a.m + b.m;
        }
    
        T m;
    };
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        Plus<A> a1, a2;
        const char* x = a1 + a2;
    
        return 0;
    }
    

    现在我还没有尝试过这段代码,因为它使用了编译器特定的东西,所以请注意它是针对 MSVC 7.x 的。因此,它可能会或可能不会与更高版本一起使用。希望是吗?

    干杯,

    【解决方案3】:

    使用 BOOST。或者,如果您不想使用所有 BOOST,这里有一个适用于 Visual Studio 2008(但可能没有其他版本)的 sn-p:

    namespace typeid_detail {
    
    template <int N>
    struct encode_counter : encode_counter<N - 1> {};
    
    template <>
    struct encode_counter<0> {};
    
    char (*encode_index(...))[5];
    // need to default to a larger value than 4, as due to MSVC's ETI errors. (sizeof(int) = 4)
    
    struct msvc_extract_type_default_param {};
    
    template <typename ID, typename T = msvc_extract_type_default_param>
    struct msvc_extract_type;
    
    template <typename ID>
    struct msvc_extract_type<ID, msvc_extract_type_default_param> {
        template <bool>
        struct id2type_impl;
    
        typedef id2type_impl<true> id2type;
    };
    
    template <typename ID, typename T>
    struct msvc_extract_type : msvc_extract_type<ID,msvc_extract_type_default_param> {
        template <>
        struct id2type_impl<true> { // VC8.0 specific bugfeature
            typedef T type;
        };
    
        template <bool>
        struct id2type_impl;
    
        typedef id2type_impl<true> id2type;
    };
    
    template <typename T, typename ID>
    struct msvc_register_type : msvc_extract_type<ID, T> {
    };
    
    template <int i>
    struct int_ {
        enum { value = i };
    };
    
    template <int ID>
    struct msvc_typeid_wrapper {
        typedef typename msvc_extract_type<int_<ID> >::id2type id2type;
        typedef typename id2type::type type;
    };
    
    template <>
    struct msvc_typeid_wrapper<1> {
        typedef msvc_typeid_wrapper<1> type;
    };
    // workaround for ETI-bug for VC6 and VC7
    
    template <>
    struct msvc_typeid_wrapper<4> {
        typedef msvc_typeid_wrapper<4> type;
    };
    // workaround for ETI-bug for VC7.1
    
    #define TYPEOF_INDEX(T) (sizeof(*encode_index((encode_counter<405/*1005*/>*)0))) // this needs to be lower for VS 2008, otherwise causes too deep templates
    #define TYPEOF_NEXT_INDEX(next) friend char (*encode_index(encode_counter<next>*))[next];
    
    template <typename T>
    struct encode_type {
        static const unsigned value = TYPEOF_INDEX(T);
        // get the next available compile time constants index
    
        typedef typename msvc_register_type<T,int_<value> >::id2type type;
        // instantiate the template
    
        static const unsigned next = value + 1;
        // set the next compile time constants index
    
        TYPEOF_NEXT_INDEX(next);
        // increment the compile time constant (only needed when extensions are not active)
    };
    
    template <class T>
    struct sizer {
        typedef char(*type)[encode_type<T>::value];
    };
    
    template <typename T> typename sizer<T>::type encode_start(T const&);
    // a function that converts a value to size-encoded type (not implemented, only needed for type inference)
    
    template <typename Organizer, typename T>
    msvc_register_type<T, Organizer> typeof_register_type(const T&, Organizer* = 0);
    
    } // ~typeid_detail
    
    #define type_of(expr) \
        typeid_detail::msvc_typeid_wrapper<sizeof(*typeid_detail::encode_start(expr))>::type
    

    并使用例如如:

    int x = 123;
    float y = 456.0f;
    typedef type_of(x+y) int_plus_float;
    int_plus_float value = x + y;
    

    当然,在使用时参考 BOOST 许可证。

    【讨论】:

    • 谢谢,但已经 5 年了。我不再使用 Visual Studio 2008 ;)
    猜你喜欢
    • 2011-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-23
    • 1970-01-01
    • 2011-04-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多