【问题标题】:Type decision based on existence of nested typedef基于嵌套 typedef 存在的类型决策
【发布时间】:2010-10-20 18:01:03
【问题描述】:

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

element<T>::type

属于:

T::element_type 

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

element<T>::type

属于类型

T::value_type 

如果 T 是可变的并且属于类型

const T::value_type

如果 T 是常数。

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

非常感谢您提前提供的帮助!

【问题讨论】:

  • 对于第一部分,您可以阅读有关 SFINAE(google it)的信息,并且您一定会找到说明您所需要的示例
  • 关于 SFINAE 的 wikipedia 文章实际上包含了一个关于检查 typedef 的示例,由您本人编写。 :P
  • 无法检测到 typedef(如果存在)是公共的。该标准明确禁止 SFINAE 使用访问限定符违规。
  • 我已经在维基百科上看到了这个例子,但是一旦我能够获得一个静态 const bool 来检测 typedef(true 或假)....这可能是微不足道的,但我不知道,对不起!这简单吗? :P
  • 更新:我现在很清楚我可以使用静态常量作为模板参数,我忘记了这一点。再次感谢。

标签: c++ templates metaprogramming


【解决方案1】:

可能是这样的:

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;
};

这当然应该被拆分和组织。

【讨论】:

  • 在结构元素中不应该是 typedef typename element_type_switch&lt;T, has_element_type&lt;T&gt;::value&gt;::type type; 而不是 typedef typename element_type_switch&lt;T, has_element_type&lt;T&gt;::value&gt; type; 吗? element_type_switch 中的相同...
  • 我测试了它并且它有效!非常感谢。我对 Potatoswapper 提出的解决方案有一点偏好(更简洁,对我来说更容易理解),但我很难编译它......谢谢大家,太糟糕了,我无法分配回答你们两个,因为你应该得到它! :)
【解决方案2】:

作为使用 SFINAE 声明特征类的替代方法,您可以通过部分特化更巧妙地使用它。

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;
};

...您可能想添加另一个案例以使element_type const 为const T?不幸的是,这在 GCC 中不起作用,尽管 Comeau 接受了它。

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;

【讨论】:

  • 对这个错误感兴趣的人,gcc.gnu.org/bugzilla/show_bug.cgi?id=46105
  • 我试过这个(使用 VS2010)但我有问题:它对 element、element 和 element 非常有效,但 element 无法编译(有和没有最后一个额外的专业化)抱怨超过 1 个匹配的部分专业化。我希望 element::type 为 has_et::element_type。再次感谢您的帮助,非常感谢!你觉得这个问题能解决吗?
  • @KRao:嗯,我试着摆弄它,但我无法让 GCC 或 Comeau 接受 const has_et 作为参数。我想我应该测试得更好 :vP 。实际上,正确性需要“额外的”专业化,但据我所知,只要包含它,它就应该可以正常工作。 (您可以删除其 typedef 中的 const,或者让它从非常量专业化派生,但它必须存在。)也许我应该将此代码放在一个新的 SO 问题中,因为我确信它是正确的......同时,我认为 GMan 的解决方案是安全的选择。
  • @KRao:嗯……事实上,Comeau 确实接受了这个代码,并且可以很好地处理所有 4 种情况。之前我也太折腾了。所以,“总有一天”,你可以使用这种更优雅的形式。
  • 感谢您的调查 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-12
  • 1970-01-01
相关资源
最近更新 更多