2014-01-16 44 views
4

我想为任意类型T创建一个容器。但是,如果T有一个成员是头类型(我也定义了),我想添加一些功能。如果T没有该头部成员,则可以跳过添加的功能。根据模板参数内容执行或跳过代码

例如,添加的功能可能是基于执行操作的时间添加时间戳。下面是伪代码,我想要的东西:

struct my_header { 
    timestamp_t time; 
    // ... etc ... 
} 

template <class T> 
class my_container { 
    public: 
    void some_operation(T val) { 
     // condition evaluated at compile time 
     if T has a member of type my_header { 
      val.header.time = get_current_time(); 
      // ... etc ... 
     } 

     // other operations, agnostic to T 
    } 
}; 
当然

,因为我有它,some_operation也有弄清楚my_header的类T的实例的名称,这个要求可以通过施加下面的一个被淘汰要用于所添加的功能要求(为了从最多到最少优选):

  • my_header在T级实例必须具有名称header
  • my_header实例是类的第一个成员变量T
  • T级导出从my_header代替包括它作为成员变量

用C++ 11细(预期实际上)。

+0

你可以根据名字'header'是'my_header'来检查,但是不知道没有类告诉你的名字。 – chris

+0

@Ken你想检查T的类型? –

+0

这究竟会如何工作?不管你如何检查变量的存在(因为'val.header.time'),代码无法编译失败。我认为解决方案将涉及专业化。 – 2014-01-16 01:02:10

回答

1

不是最好的解决方案,但我认为它可以工作。从How to detect whether there is a specific member variable in class?

#include <iostream> 
#include <type_traits> 

struct my_header { 
    int time; 
}; 

// begin stolen code 
template<typename T, typename V = bool> 
struct has_header : std::false_type { }; 

template<typename T> 
struct has_header<T, 
    typename std::enable_if< 
     !std::is_same<decltype(std::declval<T>().header), void>::value, 
     bool 
     >::type 
    > : std::true_type { }; 
// end stolen code 

struct foo 
{ 
    my_header header; 
}; 

template<typename, typename = void> 
class my_container; 

template<typename T> 
class my_container<T, typename std::enable_if<has_header<T>::value>::type> 
{ 
public: 
    T val; 
    void foo() 
    { 
     std::cout << val.header.time << "\n"; 
    } 
}; 

template <typename T> 
class my_container<T, typename std::enable_if<!has_header<T>::value>::type> 
{ 
public: 
    T val; 
    void foo() 
    { 
     std::cout << "other.\n"; 
    } 
}; 

int main() 
{ 
    my_container<foo> c; 
    my_container<int> c2; 
    c.foo(); // garbage 
    c2.foo(); // other. 
} 
+1

我想你需要通过'some_operation'上的'enable_if'来代替容器类型来优化答案 – zahir

1

remyable的解决方案窃取代码不坏(+1),但它可以简化为:

#include <iostream> 
#include <type_traits> 

struct my_header { 
    int time = 0; 
}; 

template<typename T> 
using has_header = std::is_same< decltype(T::header), my_header >; 

struct foo 
{ 
    my_header header; 
}; 

template<typename T, typename = void> 
class my_container 
{ 
public: 
    T val; 
    void foo() 
    { 
     std::cout << "other.\n"; 
    } 
}; 

template<typename T> 
class my_container<T, typename std::enable_if<has_header<T>::value>::type> 
{ 
public: 
    T val; 
    void foo() 
    { 
     std::cout << "time: " << val.header.time << "\n"; 
    } 
}; 

int main() 
{ 
    my_container<foo> c; 
    my_container<int> c2; 
    c.foo(); // time: 0 
    c2.foo(); // other. 
} 

Live example

当然,这个解决方案仍然使用要求该成员变量被称为header是C++没有内省可以迭代类型的成员。