boost::call_traits

 写C++ template程序的时候,经常遇见的问题之一就是,如何让一个函数同时支持pass by value和pass by reference,例如:

class Primitive
{
public:
    
void set(int value) ...{ m_value = value; }
private:
    
int m_value;
}
;

class Object
{
public:
    
void set(const Object& value) ...{ m_value = value; }
private:
    Object m_value;
}
;

template 
<typename T>
class Test
{
public:
    
// DO NOT DO THIS:
    
// 1) Compile error
    
// 2) Choose which one???
    void set(T value) ...{ m_value = value; }
    
void set(const T& value) ...{ m_value = value; }
private:
    Object m_value;
}
;

boost::call_traits就是用来解决这个问题的:
   #include <boost/call_traits.hpp>

template <typename T>
class Test
{
public:
    
void set(typename boost::call_traits<T>::param_type value{ m_value = value; }
private:
    T m_value;
}
;

这样的话:
Test<int> 会生成 void set(int value);
Test<Object> 会生成 void set(const Object& v);

boost是如何做到的呢?下面是一个简化的实现。boost的实现要多很多细节,但是原理是类似的。
template <typename T, bool small>
struct call_traits_i { typedef const T& type; };
 
template 
<typename T>
struct call_traits_i<T, true> { typedef T type; };
 
template 
<typename T>
struct call_traits { typedef typename call_traits_i<T, sizeof(T)<=sizeof(void*)>::type param_type; };


一点感慨:
现在C++库的建设,我感觉是走上了一条不归路。C++的库,不但要实现功能,还要实现的好,实现的高效。而其他语言的类库,最重要的是“我们有这个功能”。解掉效率的包袱,别人是一日千里,而C++们呢,望穿秋水了。。。就像Ruby设计的哲学之一就是“为程序员优化,而不是为编译器优化”。当年一直抵触去拥抱Java,感觉自己用C++,开发的效率也不慢。现在接触到了动态语言后(尤其是Ruby),真是感觉,这世界变化快呀。奶酪迟早要不见的,或缩小的,不会以个人的意愿为转移的。

没有更多推荐了,返回首页