Вывод типа в Visual C ++ 2008 - PullRequest
3 голосов
/ 27 ноября 2010

Существует ли в Microsoft Visual C ++ 2008 какой-либо механизм вывода типов для конкретного поставщика, аналогичный стандартизированному auto или decltype в C ++ 0x?

Ответы [ 3 ]

5 голосов
/ 27 ноября 2010

Нет, ничего подобного, стандартное, не зависит от производителя, не является аддоном.Вам придется обновить до VS2010, он реализует auto .

3 голосов
/ 27 ноября 2010

Цитирование из списка рассылки Boost Статья Аркадия Вертлейба:

Бог знает только, что еще можно найти внутри этого компилятора, если кто-то готов копать очень глубоко.

Например, Игорь Чесноков из RSDN (Российская сеть разработки программного обеспечения) нашел способ реализовать typeof () что не требует регистрации, и, вероятно, имеет время компиляции выступление родного typeof.

Как? Видимо, какая-то странная «фича» Visual C ++ позволил ему тикать тело шаблона на момент экземпляр, когда дополнительный контекст имеется, таким образом, "регистрация" занятия на лету, в момент взятие typeof ().

Специфичные для Microsoft «ошибки» как правило, не в области моего интересы. Однако я понимаю, что на компиляторе Microsoft, это может выглядеть намного привлекательнее все, что Педер и я реализовали. И хотя я понимаю, что это может быть серьезная конкуренция, я будет очень плохо, не говоря уже это здесь:

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

И цитирование кода Игоря Чеснокова со страницы, на которую ссылается цитируемая ссылка выше:

// 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. Так что это может или не может работать с более поздней версией. Надеюсь, это так?

Приветствия и hth.,

1 голос
/ 07 августа 2015

Используйте BOOST.Или, если вы не хотите возиться со всем 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/int x = 123;
float y = 456.0f;
typedef type_of(x+y) int_plus_float;
int_plus_float value = x + y;
/>*)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

И использовать, например, как:

*1005*

И, конечно, при использовании этой лицензии обращайтесь к лицензии BOOST.

...