C++11 如何创建模板函数以将基元和 std::vector 转换为具有最小专业化的 std::string?
C++11 How to create template function to convert primitives and std::vector to std::string with minimum specializations?
我卡住的地方在标题中描述了。
但是,也许我的全球性问题还有另一种解决方案。
有模板库class,它做了一些工作,我需要打印结果以供调试。
template<typename ResultType>
class Foo
{
public:
void PrintResult()
{
std::cout<<toString<ResultType>(result)<<std::endl;
}
virtual void Do(std::vector<void*> args)=0;
virtual ~Foo(){}
protected:
ResultType result;
};
我主要需要打印基元、std::string 和 std::vector 基元、字符串或向量。
我决定为此使用模板,但我无法为 std::vector 专门化模板。我不知道为什么它选择了错误的重载。
#include <iostream>
#include <sstream>
#include <vector>
template <typename T>
std::string toString(const T& obj)
{
return std::to_string(obj);
}
template <typename T>
std::string toString(const std::vector<T>& obj)
{
std::stringstream ss;
ss<<"[";
for(size_t i=0;i<obj.size();++i)
{
ss<<toString<T>(obj[i]);
if(i!=obj.size()-1)
ss<<", ";
}
ss<<"]";
return ss.str();
}
int main()
{
int intValue = 42;
std::vector<int> vectorOfInts;
std::vector<std::vector<double>> vectorOfVectorsOfDoubles;
std::cout<<toString<int>(intValue)<<std::endl;
std::cout<<toString<std::vector<int>>(vectorOfInts)<<std::endl;
std::cout<<toString<std::vector<std::vector<double>>>(vectorOfVectorsOfDoubles)<<std::endl;
return EXIT_SUCCESS;
}
错误:
./main.cpp:-1: In instantiation of ‘std::__cxx11::string toString(const T&) [with T = std::vector<int>; std::__cxx11::string = std::__cxx11::basic_string<char>]’:
./main.cpp:33: required from here
./main.cpp:8: error: no matching function for call to ‘to_string(const std::vector<int>&)’
return std::to_string(obj);
~~~~~~~~~~~~~~^~~~~
./main.cpp:-1: In instantiation of ‘std::__cxx11::string toString(const T&) [with T = std::vector<std::vector<double> >; std::__cxx11::string = std::__cxx11::basic_string<char>]’:
./main.cpp:34: required from here
./main.cpp:8: error: no matching function for call to ‘to_string(const std::vector<std::vector<double> >&)’
return std::to_string(obj);
~~~~~~~~~~~~~~^~~~~
编译器:
GCC 4.8(C++,x86 64 位)
是否有可能不使用所有基元和向量专门化模板函数?
我尝试从
从 c++11 修复
https://ru.whosebug.com/questions/500735/stdenable-if-t
但我仍然遇到错误:
#include <iostream>
#include <sstream>
#include <vector>
#include <type_traits>
template<bool C, class T = void>
using enable_if_t = typename std::enable_if<C, T>::type;
template<typename T>
struct is_vector
{
static constexpr bool value = false;
};
template<template<typename...> class C, typename U>
struct is_vector<C<U>>
{
static constexpr bool value =
std::is_same<C<U>,std::vector<U>>::value;
};
template <typename T>
enable_if_t<!is_vector<T>::value,std::string> toString(T& obj)
{
return std::to_string(obj);
}
template <typename T>
enable_if_t<is_vector<T>::value,std::string> toString(std::vector<T>& obj)
{
std::stringstream ss;
ss<<"[";
for(size_t i=0;i<obj.size();++i)
{
ss<<toString<T>(obj[i]);
if(i!=obj.size()-1)
ss<<", ";
}
ss<<"]";
return ss.str();
}
int main()
{
int intValue = 42;
std::vector<int> vectorOfInts;
std::vector<std::vector<double>> vectorOfVectorsOfDoubles;
std::cout<<toString<int>(intValue)<<std::endl;
std::cout<<toString<std::vector<int>>(vectorOfInts)<<std::endl;
std::cout<<toString<std::vector<std::vector<double>>>(vectorOfVectorsOfDoubles)<<std::endl;
return EXIT_SUCCESS;
}
./main.cpp:-1: In function ‘int main()’:
./main.cpp:50: error: no matching function for call to ‘toString<std::vector<int, std::allocator<int> > >(std::vector<int>&)’
std::cout<<toString<std::vector<int>>(vectorOfInts)<<std::endl;
^
./main.cpp:23: candidate: template<class T> enable_if_t<(! is_vector<T>::value), std::__cxx11::basic_string<char> > toString(T&)
enable_if_t<!is_vector<T>::value,std::string> toString(T& obj)
^~~~~~~~
./main.cpp:23: note: template argument deduction/substitution failed:
./main.cpp:29: candidate: template<class T> enable_if_t<is_vector<T>::value, std::__cxx11::basic_string<char> > toString(std::vector<T>&)
enable_if_t<is_vector<T>::value,std::string> toString(std::vector<T>& obj)
^~~~~~~~
./main.cpp:29: note: template argument deduction/substitution failed:
./main.cpp:50: note: cannot convert ‘vectorOfInts’ (type ‘std::vector<int>’) to type ‘std::vector<std::vector<int>, std::allocator<std::vector<int> > >&’
std::cout<<toString<std::vector<int>>(vectorOfInts)<<std::endl;
^
./main.cpp:51: error: no matching function for call to ‘toString<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >(std::vector<std::vector<double> >&)’
std::cout<<toString<std::vector<std::vector<double>>>(vectorOfVectorsOfDoubles)<<std::endl;
^
./main.cpp:23: candidate: template<class T> enable_if_t<(! is_vector<T>::value), std::__cxx11::basic_string<char> > toString(T&)
enable_if_t<!is_vector<T>::value,std::string> toString(T& obj)
^~~~~~~~
./main.cpp:23: note: template argument deduction/substitution failed:
./main.cpp:29: candidate: template<class T> enable_if_t<is_vector<T>::value, std::__cxx11::basic_string<char> > toString(std::vector<T>&)
enable_if_t<is_vector<T>::value,std::string> toString(std::vector<T>& obj)
^~~~~~~~
./main.cpp:29: note: template argument deduction/substitution failed:
./main.cpp:51: note: cannot convert ‘vectorOfVectorsOfDoubles’ (type ‘std::vector<std::vector<double> >’) to type ‘std::vector<std::vector<std::vector<double> >, std::allocator<std::vector<std::vector<double> > > >&’
std::cout<<toString<std::vector<std::vector<double>>>(vectorOfVectorsOfDoubles)<<std::endl;
^
您为函数调用明确选择了错误的模板实例化。如果您删除模板参数列表并让编译器自动推导它们,它会起作用:
#include <iostream>
#include <sstream>
#include <vector>
template <typename T>
std::string toString(const T& obj)
{
return std::to_string(obj); // <- no template param list
}
template <typename T>
std::string toString(const std::vector<T>& obj)
{
std::stringstream ss;
ss<<"[";
for(size_t i=0;i<obj.size();++i)
{
ss<<toString(obj[i]); // <- no template param list
if(i!=obj.size()-1)
ss<<", ";
}
ss<<"]";
return ss.str();
}
template<typename ResultType>
class Foo
{
public:
void PrintResult()
{
std::cout << toString(result)<<std::endl; // <- no template param list
}
virtual void Do(std::vector<void*> args)=0;
virtual ~Foo(){}
protected:
ResultType result;
};
int main()
{
int intValue = 42;
std::vector<int> vectorOfInts;
std::vector<std::vector<double>> vectorOfVectorsOfDoubles;
std::cout<<toString<int>(intValue)<<std::endl; // <- no template param list
std::cout<<toString(vectorOfInts)<<std::endl; // <- no template param list
std::cout<<toString(vectorOfVectorsOfDoubles)<<std::endl; // <- no template param list
return EXIT_SUCCESS;
}
我卡住的地方在标题中描述了。
但是,也许我的全球性问题还有另一种解决方案。
有模板库class,它做了一些工作,我需要打印结果以供调试。
template<typename ResultType>
class Foo
{
public:
void PrintResult()
{
std::cout<<toString<ResultType>(result)<<std::endl;
}
virtual void Do(std::vector<void*> args)=0;
virtual ~Foo(){}
protected:
ResultType result;
};
我主要需要打印基元、std::string 和 std::vector 基元、字符串或向量。
我决定为此使用模板,但我无法为 std::vector 专门化模板。我不知道为什么它选择了错误的重载。
#include <iostream>
#include <sstream>
#include <vector>
template <typename T>
std::string toString(const T& obj)
{
return std::to_string(obj);
}
template <typename T>
std::string toString(const std::vector<T>& obj)
{
std::stringstream ss;
ss<<"[";
for(size_t i=0;i<obj.size();++i)
{
ss<<toString<T>(obj[i]);
if(i!=obj.size()-1)
ss<<", ";
}
ss<<"]";
return ss.str();
}
int main()
{
int intValue = 42;
std::vector<int> vectorOfInts;
std::vector<std::vector<double>> vectorOfVectorsOfDoubles;
std::cout<<toString<int>(intValue)<<std::endl;
std::cout<<toString<std::vector<int>>(vectorOfInts)<<std::endl;
std::cout<<toString<std::vector<std::vector<double>>>(vectorOfVectorsOfDoubles)<<std::endl;
return EXIT_SUCCESS;
}
错误:
./main.cpp:-1: In instantiation of ‘std::__cxx11::string toString(const T&) [with T = std::vector<int>; std::__cxx11::string = std::__cxx11::basic_string<char>]’:
./main.cpp:33: required from here
./main.cpp:8: error: no matching function for call to ‘to_string(const std::vector<int>&)’
return std::to_string(obj);
~~~~~~~~~~~~~~^~~~~
./main.cpp:-1: In instantiation of ‘std::__cxx11::string toString(const T&) [with T = std::vector<std::vector<double> >; std::__cxx11::string = std::__cxx11::basic_string<char>]’:
./main.cpp:34: required from here
./main.cpp:8: error: no matching function for call to ‘to_string(const std::vector<std::vector<double> >&)’
return std::to_string(obj);
~~~~~~~~~~~~~~^~~~~
编译器:
GCC 4.8(C++,x86 64 位)
是否有可能不使用所有基元和向量专门化模板函数?
我尝试从
但我仍然遇到错误:
#include <iostream>
#include <sstream>
#include <vector>
#include <type_traits>
template<bool C, class T = void>
using enable_if_t = typename std::enable_if<C, T>::type;
template<typename T>
struct is_vector
{
static constexpr bool value = false;
};
template<template<typename...> class C, typename U>
struct is_vector<C<U>>
{
static constexpr bool value =
std::is_same<C<U>,std::vector<U>>::value;
};
template <typename T>
enable_if_t<!is_vector<T>::value,std::string> toString(T& obj)
{
return std::to_string(obj);
}
template <typename T>
enable_if_t<is_vector<T>::value,std::string> toString(std::vector<T>& obj)
{
std::stringstream ss;
ss<<"[";
for(size_t i=0;i<obj.size();++i)
{
ss<<toString<T>(obj[i]);
if(i!=obj.size()-1)
ss<<", ";
}
ss<<"]";
return ss.str();
}
int main()
{
int intValue = 42;
std::vector<int> vectorOfInts;
std::vector<std::vector<double>> vectorOfVectorsOfDoubles;
std::cout<<toString<int>(intValue)<<std::endl;
std::cout<<toString<std::vector<int>>(vectorOfInts)<<std::endl;
std::cout<<toString<std::vector<std::vector<double>>>(vectorOfVectorsOfDoubles)<<std::endl;
return EXIT_SUCCESS;
}
./main.cpp:-1: In function ‘int main()’:
./main.cpp:50: error: no matching function for call to ‘toString<std::vector<int, std::allocator<int> > >(std::vector<int>&)’
std::cout<<toString<std::vector<int>>(vectorOfInts)<<std::endl;
^
./main.cpp:23: candidate: template<class T> enable_if_t<(! is_vector<T>::value), std::__cxx11::basic_string<char> > toString(T&)
enable_if_t<!is_vector<T>::value,std::string> toString(T& obj)
^~~~~~~~
./main.cpp:23: note: template argument deduction/substitution failed:
./main.cpp:29: candidate: template<class T> enable_if_t<is_vector<T>::value, std::__cxx11::basic_string<char> > toString(std::vector<T>&)
enable_if_t<is_vector<T>::value,std::string> toString(std::vector<T>& obj)
^~~~~~~~
./main.cpp:29: note: template argument deduction/substitution failed:
./main.cpp:50: note: cannot convert ‘vectorOfInts’ (type ‘std::vector<int>’) to type ‘std::vector<std::vector<int>, std::allocator<std::vector<int> > >&’
std::cout<<toString<std::vector<int>>(vectorOfInts)<<std::endl;
^
./main.cpp:51: error: no matching function for call to ‘toString<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >(std::vector<std::vector<double> >&)’
std::cout<<toString<std::vector<std::vector<double>>>(vectorOfVectorsOfDoubles)<<std::endl;
^
./main.cpp:23: candidate: template<class T> enable_if_t<(! is_vector<T>::value), std::__cxx11::basic_string<char> > toString(T&)
enable_if_t<!is_vector<T>::value,std::string> toString(T& obj)
^~~~~~~~
./main.cpp:23: note: template argument deduction/substitution failed:
./main.cpp:29: candidate: template<class T> enable_if_t<is_vector<T>::value, std::__cxx11::basic_string<char> > toString(std::vector<T>&)
enable_if_t<is_vector<T>::value,std::string> toString(std::vector<T>& obj)
^~~~~~~~
./main.cpp:29: note: template argument deduction/substitution failed:
./main.cpp:51: note: cannot convert ‘vectorOfVectorsOfDoubles’ (type ‘std::vector<std::vector<double> >’) to type ‘std::vector<std::vector<std::vector<double> >, std::allocator<std::vector<std::vector<double> > > >&’
std::cout<<toString<std::vector<std::vector<double>>>(vectorOfVectorsOfDoubles)<<std::endl;
^
您为函数调用明确选择了错误的模板实例化。如果您删除模板参数列表并让编译器自动推导它们,它会起作用:
#include <iostream>
#include <sstream>
#include <vector>
template <typename T>
std::string toString(const T& obj)
{
return std::to_string(obj); // <- no template param list
}
template <typename T>
std::string toString(const std::vector<T>& obj)
{
std::stringstream ss;
ss<<"[";
for(size_t i=0;i<obj.size();++i)
{
ss<<toString(obj[i]); // <- no template param list
if(i!=obj.size()-1)
ss<<", ";
}
ss<<"]";
return ss.str();
}
template<typename ResultType>
class Foo
{
public:
void PrintResult()
{
std::cout << toString(result)<<std::endl; // <- no template param list
}
virtual void Do(std::vector<void*> args)=0;
virtual ~Foo(){}
protected:
ResultType result;
};
int main()
{
int intValue = 42;
std::vector<int> vectorOfInts;
std::vector<std::vector<double>> vectorOfVectorsOfDoubles;
std::cout<<toString<int>(intValue)<<std::endl; // <- no template param list
std::cout<<toString(vectorOfInts)<<std::endl; // <- no template param list
std::cout<<toString(vectorOfVectorsOfDoubles)<<std::endl; // <- no template param list
return EXIT_SUCCESS;
}