区分用户和非用户类型和模板专业化
Distingushing between user and non-user types & templates specialization
我需要以某种方式为用户和非用户类型重载 class 模板。问题出在模板 class 继承自模板参数:
#include <iostream>
#include<string>
#include<map>
#include<type_traits>
#include<string>
using namespace std;
class Broken_imput{};//exception class
class No_such_class{};
class Io_obj; // For MAP to know about this type
//MAP: KEY - String, VALUE - function pointer
map<string,Io_obj*(*)(istream&)> func_storage;
bool read_string(istream& ss,string& str)
{
if(ss>>str)return true; // read string from the given source
return false;
}
//------------------------------------------------
//------------------------------------------------
////CLASS THAT SETS THE INTERFACE///////////////
class Io_obj
{
public:
virtual ~Io_obj(){}
virtual void print_data()= 0;
};
//-------------------------------------------------
//FUNCTION THAT READS OBJECTS LOOKS FOR THE APPROPRIATE METHOD IN MAP AND CALLS
// IT IF METHOD EXIST. METHOD READS OBJECT OF THE TYPE IT KNOWS FROM GIVEN STREAM
Io_obj* read_object(istream& stream)
{
string str;
if(!read_string(stream,str)) throw Broken_imput{};
if(auto FN=func_storage[str])return FN(stream);
throw No_such_class{};
}
////////////////SOME CLASSES//////////////////////////////////
struct Shape
{
string data;
};
struct Circle:public Shape{};
template < class T,class = enable_if_t<is_class<U>::value,U >>
class Io:public T,public Io_obj
{
public:
Io(istream& stream){ stream>>T::data;}
void print_data() override
{
cout<<T::data<<endl;
}
//read value
static Io_obj* read_value(istream& stream) { return new Io{stream};} //deligate to constructor
};
如您所见,class Io 继承自模板参数。如果是非用户类型 (例如 int、float、char...),代码将不会被编译(当然它不应该被编译)。我需要以某种方式为非用户 types.The 标签分派和对象工厂帮助编写此模板的专业化,但我想避免使用它们。谢谢你。
仔细查看标准中的设施 header <type_traits>
。例如,如果 X
是 non-union class 类型,则 std::is_class<X>::value
是 true
,否则 false
。这些设施可用于支持您寻求的专业化。
最简单的方法是
template<class T, bool = std::is_class<T>::value>
class Io:public T,public Io_obj
{ /* ... */ };
template<class T>
class Io<T, false> : public Io_obj
{ /* ... */ };
如果这两个专业共享大量代码,您可能希望将其放在一个基础中 class 以减少代码重复。
您也可以为此使用 enable_if_t
(虽然不是问题中描述的方式),但它不必要地令人费解:
template<class T, class = void>
class Io:public T,public Io_obj
{ /* ... */ };
template<class T>
class Io<T, std::enable_if_t<!std::is_class<T>::value>> : public Io_obj
{ /* ... */ };
我需要以某种方式为用户和非用户类型重载 class 模板。问题出在模板 class 继承自模板参数:
#include <iostream>
#include<string>
#include<map>
#include<type_traits>
#include<string>
using namespace std;
class Broken_imput{};//exception class
class No_such_class{};
class Io_obj; // For MAP to know about this type
//MAP: KEY - String, VALUE - function pointer
map<string,Io_obj*(*)(istream&)> func_storage;
bool read_string(istream& ss,string& str)
{
if(ss>>str)return true; // read string from the given source
return false;
}
//------------------------------------------------
//------------------------------------------------
////CLASS THAT SETS THE INTERFACE///////////////
class Io_obj
{
public:
virtual ~Io_obj(){}
virtual void print_data()= 0;
};
//-------------------------------------------------
//FUNCTION THAT READS OBJECTS LOOKS FOR THE APPROPRIATE METHOD IN MAP AND CALLS
// IT IF METHOD EXIST. METHOD READS OBJECT OF THE TYPE IT KNOWS FROM GIVEN STREAM
Io_obj* read_object(istream& stream)
{
string str;
if(!read_string(stream,str)) throw Broken_imput{};
if(auto FN=func_storage[str])return FN(stream);
throw No_such_class{};
}
////////////////SOME CLASSES//////////////////////////////////
struct Shape
{
string data;
};
struct Circle:public Shape{};
template < class T,class = enable_if_t<is_class<U>::value,U >>
class Io:public T,public Io_obj
{
public:
Io(istream& stream){ stream>>T::data;}
void print_data() override
{
cout<<T::data<<endl;
}
//read value
static Io_obj* read_value(istream& stream) { return new Io{stream};} //deligate to constructor
};
如您所见,class Io 继承自模板参数。如果是非用户类型 (例如 int、float、char...),代码将不会被编译(当然它不应该被编译)。我需要以某种方式为非用户 types.The 标签分派和对象工厂帮助编写此模板的专业化,但我想避免使用它们。谢谢你。
仔细查看标准中的设施 header <type_traits>
。例如,如果 X
是 non-union class 类型,则 std::is_class<X>::value
是 true
,否则 false
。这些设施可用于支持您寻求的专业化。
最简单的方法是
template<class T, bool = std::is_class<T>::value>
class Io:public T,public Io_obj
{ /* ... */ };
template<class T>
class Io<T, false> : public Io_obj
{ /* ... */ };
如果这两个专业共享大量代码,您可能希望将其放在一个基础中 class 以减少代码重复。
您也可以为此使用 enable_if_t
(虽然不是问题中描述的方式),但它不必要地令人费解:
template<class T, class = void>
class Io:public T,public Io_obj
{ /* ... */ };
template<class T>
class Io<T, std::enable_if_t<!std::is_class<T>::value>> : public Io_obj
{ /* ... */ };