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

时间:2015-02-16 11:15:32

标签: c++ templates overloading c++14 template-specialization

我需要以某种方式为用户和非用户类型重载类模板。问题产生于模板类继承模板参数:

#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

};

正如您所见, 类Io 继承自模板参数。对于非用户类型(例如int,float,char ...),代码不会被编译(当然它不应该是)。我需要以某种方式为非用户类型编写此模板的专门化。标签调度&amp;对象工厂帮助,但我想避免它们。谢谢。

2 个答案:

答案 0 :(得分:2)

最简单的方法就像

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
{ /* ... */ };

如果两个专业版共享大量代码,您可能希望将其放在基类中以减少代码重复。

您也可以使用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
{ /* ... */ };

答案 1 :(得分:0)

仔细查看标准标题<type_traits>中的设施。例如,如果std::is_class<X>::value是非联合类类型,则trueX,否则为false。这些设施可用于支持您寻求的专业化。