Domanda

This is more of a question of how the C++ compiler handles const typeid calls.

Hello! I am trying to make a tuple-style class, configured in such a way that I don't have to rewrite a bunch of the code with specializations.

So this is the general idea:

struct null_type{};

template <typename T1,typename T2=null_type,typename T3=null_type>
class ptestclass
{
private:
    template<typename K1,typename K2,typename K3>
    class barclass
    {
    public:
        static inline void bar(std::tuple<K1,K2,K3>& vals,K1* otherval1,K2* otherval2,K3* otherval3)
        {
            Foo(tr1::get<0>(vals),*otherval1);
            Foo(tr1::get<1>(vals),*otherval2);
            Foo(tr1::get<2>(vals),*otherval3);
        }
    };
    template<typename K1,typename K2>
    class barclass<K1,K2,null_type>
    {
    public:
        static inline void bar(std::tuple<K1,K2,null_type>& vals,K1* otherval1,K2* otherval2,null_type* otherval3)
        {
            Foo(tr1::get<0>(vals),*otherval1);
            Foo(tr1::get<1>(vals),*otherval2);
        }
    };
    template<typename K1>
    class barclass<K1,null_type,null_type>
    {
    public:
        static inline void bar(std::tuple<K1,null_type,null_type>& vals,K1* otherval1,null_type* otherval2,null_type* otherval3)
        {
            Foo(tr1::get<0>(vals),*otherval1);
        }
    };

    /*
     *Old Bar function...much more readable than bar class, but you cannot partially specialize
     *member functions of a class
     *
    void inline bar(std::tuple<T1,T2,T3> otherval)
    {
        if (typeid(T1) != typeid(null_type))//constant check hopfully optomized out
        {
            Foo(vals.get(1),otherval.get(1));
        }
        if (typeid(T2) != typeid(null_type))//constant check hopfully optomized out
        {
            Foo(vals.get(2),otherval.get(2));
        }
        if(typeid(T3) != typeid(null_type))//constant check hopfully optomized out
        {
            Foo(vals.get(3),otherval.get(3));
        }

    }
     */
    std::tuple<T1,T2,T3> vals;



    template<typename K>
    void static inline Foo(K& val,K& otherval)
    {
        //inlineable, short function that is called many (millions) of times per iteration
        val += otherval;
    }

    template<>
    void inline Foo<null_type>(null_type& val,null_type& otherval)
    {
        //inlineable, short function that is called many (millions) of times per iteration
        throw "Foo called on null type";
    }

public:
    ptestclass()
    {
        printf("made object");
    }
    void one_iteration(T1* otherval1,T2* otherval2,T3* otherval3,size_t count)
    {
        for (int i = 0; i < count; ++i)
        {
            barclass<T1,T2,T3>::bar(vals,otherval1+i,otherval2+i,otherval3+i);
        }
    }
};

//exposed public class with specialized one_iteration interfaces
template <typename T1,typename T2=null_type,typename T3=null_type>
class testclass : public ptestclass<T1,T2,T3>
{
public:
    void one_iteration(T1* otherval1,T1* otherval2,T1* otherval3,size_t count)
    {
        ptestclass::one_iteration(otherval1,otherval2,otherval3,count);
    }
};

template <typename T1>
class testclass<T1,null_type,null_type> : public ptestclass<T1,null_type,null_type>
{
public:
    void one_iteration(T1* otherval1,size_t count)
    {
        ptestclass::one_iteration(otherval1,NULL,NULL,count);
    }
};

So my question is is this optimization even possible within C++? If not, it will probably make more sense for me to use an inheritance model on the child nodes rather then a template at this level. However, I am trying to avoid the continual check of the number of types specified and the cost of indirection.

I'm going to start diving into the assembly to see if that is what the compiler does...Just in case this is not standardized behavior, I'm using the Microsoft Visual C++ Compiler 10.0.

È stato utile?

Soluzione

I think I misunderstood your question when I put my earlier comment.

Assuming you can use c++11, or you can use boost, you could use something like !std::is_same< T1, null_type >::value /*or boost::is_same...*/ instead of typeid(T1) != typeid(null_type). This uses TMP to resolve to a compile-time constant, which most compilers would have no trouble optimizing away.

This is more of a question of how the C++ compiler handles const typeid calls.

I didn't answer this specific question, but if I understand what you were actually looking for, the above should suffice.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top