区分用户和非用户类型和模板专业化

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>::valuetrue,否则 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
{ /* ... */ };