使用enable_if可选择添加结构成员

时间:2012-04-13 11:48:29

标签: c++ metaprogramming enable-if

鉴于此模板:

template <class A>
struct Something {
    ... // members common to all template instantiations for all A types 
    SpecialType member; // but not this - I want this to be conditional...
}

...我想使用“enable_if”使SpecialType成员有条件存在;也就是说,只有在使用A = SpecialCase1或SpecialCase2类型实例化模板时。在所有其他情况下,我希望SpecialType成员丢失。

如果你想知道为什么,这是关于优化 - 即不在结构中携带无用的有效载荷。我是模板元编程的新手,但我知道我需要“enable_if”和两个“is_same” - 不确定究竟是怎么做的,但是......

编辑:使用通用C ++(即没有特定于Boost)是一件好事。

4 个答案:

答案 0 :(得分:5)

你不需要enable_if。专门针对特殊情况的结构,并保留其余的默认实现:

template <class A>
struct Something
{
  // your default implementation
};

template <>
struct Something<SpecialCase1>
{
  // your SpecialCase1 implementation
};

template <>
struct Something<SpecialCase2>
{
  // your SpecialCase2 implementation
};

答案 1 :(得分:5)

好吧:使用基类。

struct Empty {};

struct SpecialTypeCnt { SpecialType member; };

template <typename A>
struct Something: if_< /* cond */ , SpecialTypeCnt, Empty>::type {
};

if_定义为:

template <typename, typename, typename E> struct if_ { typedef E type; };

template <typename T, typename E>
struct if_<std::true_type, T, E> { typedef T type; };

(你也可以专注于布尔值)

当然,你需要正确表达你的状况。


话虽如此,你可能不应该只使用struct。相反,您应该使用class来提供需要在member上应用的操作。然后,您提供class Null的默认行为和class SomeType,其行为特定于member

否则你会在需要“或许”修改member的任何地方重写条件,而且它会很快变得烦人。

答案 2 :(得分:2)

为了不复制普通会员:

定义BaseSomething类:

 template <class A>
        struct BaseSomething {
            ... // members common to all template instantiations for all A types 
                };

定义SpecialSomething类:

template <class A>
            struct SpecialSomething {
                SpecialType member;
                ...//SpetialType related functionality
                    };

定义Something类:

template <class A>
            struct Something :public BaseSomething<A>{

                    };



  template<>
    struct Something<SpecialCase1>:public BaseSomething<A>{
                    SpecialSomething<SpecialCase1> special;
                        };


template<>
struct Something<SpecialCase2>:public BaseSomething<A>{
                SpecialSomething<SpecialCase2> special;
                    };

答案 3 :(得分:1)

马蒂厄(Matthieu M)已经回答了这个问题。但是,在意识形态和优雅方面要稍微解决一点,那就是执行以下操作:

struct OptionalMembers { SpecialType member; };

template <typename T>
    class Something: public conditional_t<is_same<T, SpecialCase>, OptionalMembers, tuple<>> {
};

此示例显示了仅当模板参数的类型为SpecialCase时如何添加可选成员。