我使用了以下代码,它可以很好地用 printContainer()打印一个简单的std :: vector。
我现在想用 printContainerV2()
为嵌套容器扩展它
我已经尝试使用模板来确定该类型是否是一个stl容器,但它似乎不是这样做的。
#include <iostream>
#include <iterator>
#include <vector>
template <typename Iter, typename Cont>
bool isLast(Iter iter, const Cont& cont)
{
return (iter != cont.end()) && (next(iter) == cont.end());
}
template <typename T>
struct is_cont {
static const bool value = false;
};
template <typename T,typename Alloc>
struct is_cont<std::vector<T,Alloc> > {
static const bool value = true;
};
template <typename T>
std::string printContainer(T const& container)
{
std::string str = "{";
for (auto it = std::begin(container); it != std::end(container); ++ it)
if (isLast(it, container))
str = str + std::to_string(*it) + "}";
else
str = str + std::to_string(*it) + ",";
return str;
}
/*
template <typename T>
std::string printContainerV2(T const& container)
{
std::string str = "{";
for (auto it = std::begin(container); it != std::end(container); ++ it)
if (isLast(it, container))
if (is_cont<decltype(*it)>::value == true)
str = str + printContainer(*it);
else
str = str + std::to_string(*it) + "}";
else
if (is_cont<decltype(*it))>::value == true)
str = str + printContainer(*it);
else
str = str + std::to_string(*it) + ",";
return str;
}
*/
int main()
{
std::vector<int> A({2,3,6,8});
std::vector<std::vector<int>> M(2,A);
M[1][0] ++;
std::cout << is_cont<decltype(A)>::value << std::endl; // returns true !
for (auto it = std::begin(M); it != std::end(M); ++ it)
{
std::cout << printContainer(*it) << std::endl; // works well std::vector<int>
std::cout << is_cont<decltype(*it)>::value << std::endl; // return false :(
}
// Want to use this for printing a std::vector<std::vector<int>>
// std::cout << printContainerV2(M) << std::endl; // not working !
}
目前,如果代码仅适用于std :: vector类型和最多一个嵌套级别(std :: vector&lt; std :: vector&gt;&gt;),则可以。我不确定没有努力就可以通用......
答案 0 :(得分:5)
添加#include <type_traits>
标题,并将PrintContainerV2
替换为:
template<typename T>
using if_not_cont = std::enable_if<!is_cont<T>::value>;
template<typename T>
using if_cont = std::enable_if<is_cont<T>::value>;
template <typename T, typename if_not_cont<T>::type* = nullptr>
std::string printContainerV2(T const& container)
{
std::string str = "{";
for (auto it = std::begin(container); it != std::end(container); ++ it)
if (isLast(it, container))
str = str + std::to_string(*it) + "}";
else
str = str + std::to_string(*it) + ",";
return str;
}
template <typename T, typename if_cont<T>::type* = nullptr>
std::string printContainerV2(T const& container)
{
std::string str = "{";
for (auto it = std::begin(container); it != std::end(container); ++ it)
if (isLast(it, container))
str = str + printContainer(*it) + "}";
else
str = str + printContainer(*it) + ",";
return str;
}
答案 1 :(得分:4)
您的解决方案不起作用的原因在于:
if (is_cont<decltype(*it)>::value == true)
str = str + printContainer(*it);
else
str = str + std::to_string(*it) + "}"; // <====
即使您正在进行的检查是静态编译时间 - 仍然会编译if
的两个分支。编译器仍会尝试评估std::to_string(std::vector<T> )
并抱怨该函数不存在。我们需要做的是使用SFINAE:替换失败不是错误。
这是我们的print
容器版本:
template <typename T>
std::enable_if_t<is_cont<T>::value, std::string>
print(const T& container)
{
// mostly the same as your code from printContainer() here, except instead of
// std::to_string(*it), call print(*it).
std::string str = "{";
for (auto it = std::begin(container); it != std::end(container); ++ it)
{
str += print(*it);
if (isLast(it, container)) {
str += '}';
}
else {
str += ',';
}
}
return str;
}
非容器版本:
template <typename T>
std::enable_if_t<!is_cont<T>::value, std::string>
print(const T& value)
{
return std::to_string(value);
}
这逻辑上与您在printContainerV2()
中执行的操作相同,但这样else
分支 - to_string()
分支 - 将无法获得为实际容器版本编译。
答案 2 :(得分:2)
我修改了你的代码,最后我有了解决方案:
#include <iostream>
#include <iterator>
#include <vector>
#include <string>
using namespace std;
template <class N>
struct is_vector { static const int value = 0; };
template <class N, class A>
struct is_vector<std::vector<N, A> > { static const int value = 1; };
struct container_true {};
struct container_false {};
template <typename T>
std::string print(T const& container);
template <typename T>
std::string printContainer(T const& container, container_true)
{
std::string ret = "{";
for (auto it = std::begin(container); it != std::end(container); ++it)
{
ret += "{";
ret += print(*it);
ret += "}";
}
ret += "}";
return ret;
}
template <typename T>
std::string printContainer(T const& container, container_false)
{
std::string ret;
for (auto it = std::begin(container); it != std::end(container); ++it)
{
ret += to_string(*it) + ",";
}
return ret.erase(ret.size() - 1);;
}
template <typename T>
std::string print(T const& container)
{
typename std::conditional<is_vector<T::value_type>::value, container_true, container_false>::type mys;
return printContainer(container, mys);
}
int main()
{
std::vector<int> A({ 2, 3, 6, 8 });
std::vector<std::vector<int>> M(2, A);
M[1][0]++;
std::vector<std::vector<std::vector<int>>> Z(2, M);
std::cout << print(A) << std::endl;
std::cout << print(M) << std::endl;
std::cout << print(Z) << std::endl;
}
编辑:更短的解决方案:
#include <iostream>
#include <vector>
#include <string>
template <class N>
struct is_vector { static const int value = 0; };
template <class N, class A>
struct is_vector<std::vector<N, A> > { static const int value = 1; };
template <typename T>
std::enable_if_t< is_vector<typename T::value_type>::value, std::string>
printContainer(T const& container)
{
std::string ret = "{";
for (auto& a : container)
ret += "{" + printContainer(a) + "}";
return ret + '}';
}
template <typename T>
std::enable_if_t< !is_vector<typename T::value_type>::value, std::string>
printContainer(T const& container)
{
std::string ret;
for (auto& a : container)
ret += std::to_string(a) + ",";
return ret.erase(ret.size() - 1);;
}
int main()
{
std::vector<int> A({ 2, 3, 6, 8 });
std::cout << printContainer(A) << std::endl;
}
答案 3 :(得分:0)
我认为我的解决方案是递归的。我可以打印任何嵌套的矢量。
main.cpp
#include "vector.h"
int main(){
std::vector<std::vector<std::vector<int>>> e = {{{1,2,3},{4,5,6},{7,8,9}},{{9,8,7},{6,5,4},{3,2,1}}};
std::cout << e << std::endl;
return 0;
}
&#34; vector.h&#34;
#ifndef VECTOR_H
#define VECTOR_H
#include <vector>
#include <iostream>
template<typename T1>
std::ostream& operator<<(std::ostream& stream, std::vector<T1> r){
if(r.size() == 0){
return stream;
}
else{
stream << "(";
for(int i = 0; i < r.size(); i++){
if(i < (r.size() - 1)){
stream << r[i] << ", ";
}
else{
stream << r[i] << ")";
}
}
}
return stream;
};
#endif