0

これは、C++コンパイラがconsttypeid呼び出しをどのように処理するかという問題です。

こんにちは!特殊化されたコードの束を書き直す必要がないように構成されたタプルスタイルのクラスを作成しようとしています。

したがって、これは一般的な考え方です。

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);
    }
};

だから私の質問は、この最適化はC ++内でも可能ですか?そうでない場合は、このレベルのテンプレートではなく、子ノードで継承モデルを使用する方がおそらく理にかなっています。ただし、指定されたタイプの数と間接参照のコストを継続的にチェックすることは避けようとしています。

アセンブリに飛び込んで、それがコンパイラの機能であるかどうかを確認します...これが標準化された動作でない場合に備えて、Microsoft VisualC++コンパイラ10.0を使用しています。

4

1 に答える 1

1

以前のコメントをしたときに、あなたの質問を誤解したと思います。

c++11 を使用できる、またはブーストを使用できると仮定すると!std::is_same< T1, null_type >::value /*or boost::is_same...*/、typeid(T1) != typeid(null_type) の代わりに次のようなものを使用できます。これは、TMP を使用してコンパイル時の定数を解決します。ほとんどのコンパイラは最適化で問題なく削除できます。

これは、C++ コンパイラが const typeid 呼び出しをどのように処理するかという問題です。

この特定の質問には答えませんでしたが、あなたが実際に探していたものを理解していれば、上記で十分です。

于 2013-03-19T18:48:01.900 に答える