【发布时间】:2010-11-27 14:20:50
【问题描述】:
Microsoft Visual C++ 2008 中是否有一些特定于供应商的类型推断机制,类似于 C++0x 中的标准化 auto 或 decltype?
【问题讨论】:
标签: c++ visual-c++ c++11 type-inference decltype
Microsoft Visual C++ 2008 中是否有一些特定于供应商的类型推断机制,类似于 C++0x 中的标准化 auto 或 decltype?
【问题讨论】:
标签: c++ visual-c++ c++11 type-inference decltype
不,不是这样的,标准的、供应商特定的或插件。你必须升级到 VS2010,它实现了 auto。
【讨论】:
引用 Arkadiy Vertleyb 的 Boost mailing list 文章:
只有上帝知道还能找到什么 如果愿意的话,在这个编译器里面 深入挖掘。
例如,来自 RSDN 的 Igor' Chesnokov (俄罗斯软件开发网) 找到了实现 typeof() 的方法 不需要注册, 并且可能有编译时间 原生 typeof 的性能。
怎么样?显然,一些奇怪的“功能” Visual C++ 允许他 模板正文 实例化,当附加上下文 可用,因此“注册” 即时上课,此刻 采用 typeof()。
微软特有的“bugfeatures”是 一般不在我的范围内 利益。然而我确实意识到, 在 Microsoft 编译器上,这可能 看起来更有吸引力 佩德和我已经实施的任何事情。 即使我意识到这 可能是一场严肃的比赛,我 更不用说会感觉很糟糕 这里:
并从上面引用的链接引用的页面中引用 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 的。因此,它可能会或可能不会与更高版本一起使用。希望是吗?
干杯,
使用 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 许可证。
【讨论】: