具有公共基础的派生类的模板特化

时间:2018-01-14 20:28:28

标签: c++ templates lambda

我想为名称未知的类进行模板特化,我只知道它们的基础,并且我希望所有派生类都落在专门的模板函数上。

以下代码适用于案例1-4。我无法使案例5起作用。 这也主要是使用is_base_of进行运行时检查,更有效的是编译时解决方案,但我失败了。 :(

#include <typeinfo>
#include <iostream>

struct MyClass {};
struct Rnd : public MyClass {};
void* JustAVoidPointer=new int;
void* AnOtherPointer = new int;

struct A
{
    template <typename T> operator T() const {
        if (std::is_base_of<MyClass, T>::value == true)
        {
            JustAVoidPointer = (MyClass*)(new T);
            std::cout << "Case 3"; return *((T*)(JustAVoidPointer)); 
        }
        std::cout << "Case 1"; return *((T*)AnOtherPointer); 
    }
    //template <typename T> operator T&()  {
    //  std::cout << "Case 5"; return *(this->operator T* ());
    //}
    template <typename T> operator T*() const {
        if (std::is_base_of<MyClass, T>::value == true)
        {
            JustAVoidPointer = (MyClass*) new T;
            std::cout << "Case 4"; return (T*)(JustAVoidPointer); 
        }
        std::cout << "Case 2"; return *((T**)AnOtherPointer); 
    }
}a;

void main()
{
    auto CantUseTheStructsName = [&]() {
        struct Rnd : public MyClass {};
        int z = a; //Case 1
        int* w = a; //Case 2
        Rnd x = a; //Case 3
        Rnd* y = a; //Case 4
        //Rnd& z=a; //Case 5
        char* xx=0; std::cin >> xx;
    }; CantUseTheStructsName();
}

感谢您给我的任何帮助或建议,谢谢!:)

1 个答案:

答案 0 :(得分:0)

我感觉不可能区分参考操作员模板和非参考操作员模板,如果我们提供两者,参考操作员模板总是优先考虑。 解决方法和编译时解决方案:

#include <typeinfo>
#include <iostream>

struct MyClass {};
struct Rnd : public MyClass {};
void* JustAVoidPointer=0;
void* AnOtherPointer = new int;

struct A
{
    template <typename T, typename F = T*> operator T&() const {
        return *((T*)CheckType(F{}, std::is_pointer<T>{}, std::is_base_of<MyClass, std::remove_pointer<T>::type>{}));
    }

    template <typename T> T* CheckType(T*, std::false_type, std::false_type) const {
        std::cout << "  Case 1";
        return ((T*)AnOtherPointer);
    }
    template <typename T> T* CheckType(T*, std::true_type, std::false_type) const {
        std::cout << "  Case 2";
        return ((T*)AnOtherPointer);
    }
    template <typename T> T* CheckType(T*, std::false_type, std::true_type) const {
        std::cout << "  Case 3";
        JustAVoidPointer = (MyClass*)(new T);
        return ((T*)JustAVoidPointer);
    }
    template <typename T> T* CheckType(T*, std::true_type, std::true_type) const {
        std::cout << "  Case 4";
        JustAVoidPointer = (MyClass*)(new std::remove_pointer<T>::type);
        return ((T*)(&JustAVoidPointer));
    }
}a;


void main()
{
    auto CantUseTheStructsName = [&]() {
        struct Rnd : public MyClass {};
        int x = a; //Case 1
        int& y = a; //Case 1
        int* z = a; //Case 2
        Rnd j = a; //Case 3
        Rnd& k = a; //Case 3
        Rnd* f = a; //Case 4
        char* xx=0; std::cin >> xx;
    }; CantUseTheStructsName();
}