写C++ template程序的时候,经常遇见的问题之一就是,如何让一个函数同时支持pass by value和pass by reference,例如:
boost::call_traits就是用来解决这个问题的:
这样的话:
Test<int> 会生成 void set(int value);
Test<Object> 会生成 void set(const Object& v);
boost是如何做到的呢?下面是一个简化的实现。boost的实现要多很多细节,但是原理是类似的。
一点感慨:
现在C++库的建设,我感觉是走上了一条不归路。C++的库,不但要实现功能,还要实现的好,实现的高效。而其他语言的类库,最重要的是“我们有这个功能”。解掉效率的包袱,别人是一日千里,而C++们呢,望穿秋水了。。。就像Ruby设计的哲学之一就是“为程序员优化,而不是为编译器优化”。当年一直抵触去拥抱Java,感觉自己用C++,开发的效率也不慢。现在接触到了动态语言后(尤其是Ruby),真是感觉,这世界变化快呀。奶酪迟早要不见的,或缩小的,不会以个人的意愿为转移的。
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;
} ;
{
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;
} ;
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; } ;
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),真是感觉,这世界变化快呀。奶酪迟早要不见的,或缩小的,不会以个人的意愿为转移的。