2014-10-09 94 views
0

我想用C写一个通用的函数++泛型函数来获取所有类型和集合在C++

template<class T> 
string GetDebugString(const T& t); 

从而可以得到普遍调试字符串为所有类型的调试字符串。我的问题是如何使用特征区分不同类型:

1)原始类型和字符串: 直接获取其字符串表示形式。

2)结构和类的类型: 调用它的“字符串DebugString()”方法。我会为所有类实现这个方法。该方法可能会递归调用GetDebugString。

3)指针和智能指针: 解除引用它们,并按照1)或2)

4)类别像向量,设定或地图: 遍历其所有元件,获得的调试串对于每个元件以下1 ),2)和3)并以某种格式组装它们。

我们如何用std :: enable_if做到这一点?

+0

您可以使用SFINAE来检查您是否正在使用'DebugString'方法处理类型,并为您提及的其他所有内容重载。没有必要的特质。如果您按照这些条款进行搜索,则应该能够复制/抓取某些内容并针对特定问题寻求帮助。 – 2014-10-09 17:32:18

+0

我可以使用C++ 11。 – yuefengz 2014-10-09 17:32:41

+0

这可以帮助你:http://stackoverflow.com/questions/4850473/pretty-print-c-stl-containers – Chnossos 2014-10-09 17:32:54

回答

1

一种方法是使用专业化来编写类型特定的实现。例如:

template<> 
string GetDebugString(int& t) 
{ 
    return "It's an int"; 
} 

template<> 
string GetDebugString(string& t) 
{ 
    return t; 
} 

template <class T> 
string GetDebugString(T& t) 
{ 
    //Now that you've taken care of the special cases 
    //write a function to handle the generic 

} 
1

大致是这样的:

#include <iostream> 

#define AUTO_RETURN(...) -> decltype(__VA_ARGS__) {return (__VA_ARGS__);} 

std::string GetDebugString(char ch) {return {ch};} 
std::string GetDebugString(char const* str) {return str;} 
std::string GetDebugString(std::string const& str) {return str;} 

template <typename T> 
auto GetDebugString(T t) AUTO_RETURN(std::to_string(t)) 

// No AUTO_RETURN here because of GCC 
template <typename T> 
auto GetDebugString(T ptr) -> decltype(GetDebugString(*ptr)) 
{ 
    return "Pointer to " + GetDebugString(*ptr); 
} 

template <typename T> 
auto GetDebugString(T&& t) AUTO_RETURN(std::forward<T>(t).DebugString()) 

template <typename T, typename U> 
auto GetDebugString(std::pair<T, U> const& p) AUTO_RETURN('<' + GetDebugString(p.first) + ',' + GetDebugString(p.second) + '>') 

template <typename Range> 
auto GetDebugString(Range&& c) -> decltype(std::begin(c), std::end(c), std::string()) 
{ 
    // Size obtainment can be optimized for containers with size member-functions 
    std::string str = "Range with " + std::to_string(std::distance(std::begin(c), std::end(c))) + " elements: \n\t"; 
    for (auto const& elem : c) 
     str += GetDebugString(elem) + ", "; 
    return str; 
} 

int main() 
{ 
    int i = 23; 
    auto ptr = &i; 
    char const str[] = "Hallo!"; 
    auto list = {4, 5, 5, 6, 8}; 

    std::cout << GetDebugString(i) << '\n'; 
    std::cout << GetDebugString(ptr) << '\n'; 
    std::cout << GetDebugString(str) << '\n'; 
    std::cout << GetDebugString(list) << '\n'; 
} 

Demo。 请注意,您可能必须引入排名以避免含糊不清;例如当一个类型同时具有DebugString方法以及begin/end成员函数时。为了简单起见,我没有使用ADL范围访问。

+0

您还可以告诉我如何处理map吗? – yuefengz 2014-10-10 04:32:04

+0

@Fake为“对”添加了重载。 – Columbo 2014-10-10 07:17:30

+0

谢谢。那么是否有可能为地图设置单独的GetDebugString? – yuefengz 2014-10-10 16:45:01