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

Visual C++ 2008中的类型推理

  •  3
  • fredoverflow  · 技术社区  · 15 年前

    在微软Visual C++ 2008中是否存在类似于标准化的特定于供应商的类型推理机制? auto 或 decltype 在C++ 0x中?

    3 回复  |  直到 11 年前
        1
  •  5
  •   Hans Passant    15 年前

    不,没有类似的,标准的,供应商特定的,附加的。你必须升级到VS2010,它实现了 汽车 .

        2
  •  3
  •   Cheers and hth. - Alf    15 年前

    从A引用 Boost mailing list Arkadiy Vertleyb的文章:

    上帝只知道还能找到什么 如果愿意的话,在这个编译器内部 挖得很深。

    例如,来自RSDN的igor'chesnokov (俄罗斯软件开发网络) 已找到实现typeof()的方法 不需要注册, 可能还有编译时间 本机类型的性能。

    怎样?显然,一些奇怪的“特征” VisualC++让他变 模板主体 实例化,当附加上下文 可用,因此“注册” 就在这一刻, 正在获取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
  •  1
  •   the swine    11 年前

    使用Boost。或者,如果您不想全力以赴,这里有一个片段可以与Visual Studio 2008一起使用(但可能没有其他版本):

    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许可证。