Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 基于嵌套typedef存在性的类型决策_C++_Templates_Metaprogramming - Fatal编程技术网

C++ 基于嵌套typedef存在性的类型决策

C++ 基于嵌套typedef存在性的类型决策,c++,templates,metaprogramming,C++,Templates,Metaprogramming,我需要定义一个模板结构,以便: element<T>::type 如果T包含一个名为element_type的(公共)typedef,否则(如果它不包含这样的typedef) 如果T是可变的且类型为 const T::value_type 如果T是常数 我真的很挣扎,任何建议都非常感谢!:) 非常感谢您事先的帮助 可能类似于: template <typename T> struct has_element_type { typedef char yes[1]

我需要定义一个模板结构,以便:

element<T>::type
如果T包含一个名为element_type的(公共)typedef,否则(如果它不包含这样的typedef)

如果T是可变的且类型为

const T::value_type
如果T是常数

我真的很挣扎,任何建议都非常感谢!:)

非常感谢您事先的帮助

可能类似于:

template <typename T>
struct has_element_type
{
    typedef char yes[1];
    typedef char no[2];

    template <typename C>
    static yes& test(typename C::element_type*);

    template <typename>
    static no& test(...);

    static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};

template <typename T>
struct is_const
{
    static const bool value = false;
};


template <typename T>
struct is_const<const T>
{
    static const bool value = true;
};

template <typename, bool> // true -> const
struct value_type_switch; 

template <typename T>
struct value_type_switch<T, true>
{
    typedef const typename T::value_type type;
};

template <typename T>
struct value_type_switch<T, false>
{
    typedef typename T::value_type type;
};

template <typename, bool> // true -> has element_type
struct element_type_switch;

template <typename T>
struct element_type_switch<T, true>
{
    typedef typename T::element_type type;
};


template <typename T>
struct element_type_switch<T, false>
{
    typedef typename value_type_switch<T, is_const<T>::value>::type type;
};

template <typename T>
struct element
{
    typedef typename element_type_switch<T,
                                    has_element_type<T>::value>::type type;
};
模板
结构具有\u元素\u类型
{
typedef char yes[1];
typedef字符编号[2];
模板
静态是&测试(typename C::element_type*);
模板
静态no&test(…);
静态常量布尔值=sizeof(测试(0))==sizeof(是);
};
模板
结构是常量
{
静态常量布尔值=假;
};
模板
结构是常量
{
静态常量布尔值=真;
};
模板//true->const
结构值类型开关;
模板
结构值类型开关
{
typedef const typename T::value_type类型;
};
模板
结构值类型开关
{
typedef typename T::value_type type;
};
模板//真->具有元素类型
结构元素类型开关;
模板
结构元素类型开关
{
typedef typename T::element_type type;
};
模板
结构元素类型开关
{
typedef typename value_type_开关::type type;
};
模板
结构元素
{
typedef typename元素\类型\开关::类型类型;
};

当然,这应该被分解和组织。

作为使用SFINAE声明traits类的替代方法,您可以更巧妙地将其用于部分专门化

template< typename T >
struct empty { // support class is like stripped-down enable_if
    typedef void type;
};

template< class T, typename v = void > // v is always void!
struct element {
    typedef typename T::value_type type;
};

template< class T, typename v >
struct element< T const, v > {
    typedef typename T::value_type const type;
};

template< class T > // T in deduced context, T::element_type is SFINAE:
struct element< T, typename empty< typename T::element_type >::type > {
    typedef typename T::element_type type;
};
我用来测试这一点的代码:

struct has_et {
    typedef int element_type;
};

struct has_vt {
    typedef char value_type;
};

char c;
int i;

element<has_vt>::type *cp = &c;
element<has_et>::type *ip = &i;
struct具有{
typedef int-element_-type;
};
结构有{
typedef char value_type;
};
字符c;
int i;
元素::类型*cp=&c;
元素::类型*ip=&i;

在第一部分,你可以阅读关于SFINAE(谷歌it)的文章,你一定会找到一些例子来说明你需要什么。关于SFINAE的维基百科文章实际上包含了一个关于检查typedef的例子,由你的Really编写:p无法检测typedef(如果存在)是否是公共的。该标准明确禁止SFINAE处理访问限定符冲突。我已经在wikipedia上看到了该示例,但一旦我能够获取用于检测typedef的静态常量(真或假),我就无法找到如何获取我感兴趣的类型。。。。这可能是微不足道的,但我不知道,对不起!容易吗PUpdate:现在我很清楚我可以使用静态常量作为模板参数,我忘了这个。再次感谢。在struct元素中不应该是
typedef-typename-element\u-type\u-switch::type-type而不是
typedef typename元素\类型\开关类型?相同的in-element_-type_开关…我测试了它,它工作正常!非常感谢你。我对Potatoswapper提出的解决方案有一点偏好(更简洁,对我来说更容易理解),但我很难让它编译。。。谢谢大家,太糟糕了,我不能给你们两个分配一个答案,因为这是你们应得的!:)对于那些对这个bug感兴趣的人,我尝试了这个方法(使用VS2010),但我遇到了一个问题:它对元素、元素和元素都非常有效,但是元素无法编译(有和没有最后一个额外的专门化),抱怨超过1个匹配的部分专门化。我希望元素::类型为has_et::element_类型。再次感谢您的帮助,非常感谢!你认为这个问题可以解决吗?@KRao:嗯,我试着摆弄它,但我无法让GCC或Comeau接受const has_et
作为一个参数。我想我应该考得更好:副总裁。事实上,正确性需要“附加”专门化,但据我所知,只要包含它,它就应该正常工作。(您可以删除其typedef中的
const
,或者让它派生自非const专门化,但它必须存在。)也许我应该将此代码放在一个新的SO问题中,因为我确信它是正确的……同时,我认为GMan的解决方案是一个安全的选择。@KRao:嗯……事实证明,Comeau确实接受了这个代码,并且可以完美地处理所有4个案例。我以前玩得太多了。所以,“有一天”,你可以用这个更优雅的形式。谢谢你的调查:)
template <typename T>
struct has_element_type
{
    typedef char yes[1];
    typedef char no[2];

    template <typename C>
    static yes& test(typename C::element_type*);

    template <typename>
    static no& test(...);

    static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};

template <typename T>
struct is_const
{
    static const bool value = false;
};


template <typename T>
struct is_const<const T>
{
    static const bool value = true;
};

template <typename, bool> // true -> const
struct value_type_switch; 

template <typename T>
struct value_type_switch<T, true>
{
    typedef const typename T::value_type type;
};

template <typename T>
struct value_type_switch<T, false>
{
    typedef typename T::value_type type;
};

template <typename, bool> // true -> has element_type
struct element_type_switch;

template <typename T>
struct element_type_switch<T, true>
{
    typedef typename T::element_type type;
};


template <typename T>
struct element_type_switch<T, false>
{
    typedef typename value_type_switch<T, is_const<T>::value>::type type;
};

template <typename T>
struct element
{
    typedef typename element_type_switch<T,
                                    has_element_type<T>::value>::type type;
};
template< typename T >
struct empty { // support class is like stripped-down enable_if
    typedef void type;
};

template< class T, typename v = void > // v is always void!
struct element {
    typedef typename T::value_type type;
};

template< class T, typename v >
struct element< T const, v > {
    typedef typename T::value_type const type;
};

template< class T > // T in deduced context, T::element_type is SFINAE:
struct element< T, typename empty< typename T::element_type >::type > {
    typedef typename T::element_type type;
};
template< class T >
struct element< T const, typename empty< typename T::element_type >::type > {
    typedef typename T::element_type const type;
};
struct has_et {
    typedef int element_type;
};

struct has_vt {
    typedef char value_type;
};

char c;
int i;

element<has_vt>::type *cp = &c;
element<has_et>::type *ip = &i;