4

テンプレートパラメータに応じてメソッドシグネチャが変化するクラステンプレートを作成しようとしています。私の目標は、コードの重複をできるだけ少なくすることです。この例を考えてみましょう。最初にクラス宣言を行います。

// a.hxx
#ifndef A_HXX
#define A_HXX

template<typename T>
struct A
{
    void foo(T value) const;
    void bar() const;
};

#include <string>

#ifndef short_declaration
template<>
struct A<std::string>
{
    void foo(const std::string &value) const;
    void bar() const;
};
#else // short_declaration
template<>
struct A<std::string>
{
    void foo(const std::string &value) const;
};
#endif // short_declaration

#endif // A_HXX

次に、クラス定義:

// a_impl.hxx
#ifndef A_IMPL_HXX
#define A_IMPL_HXX

#include "a.hxx"
#include <iostream>
#include <typeinfo>

template<typename T>
void A<T>::foo(T value) const
{
    std::cout << "A<T=" << typeid(T).name() << ">::foo(" << value << ")"
        << std::endl;
}

template<typename T>
void A<T>::bar() const
{
    std::cout << "A<T=" << typeid(T).name() << ">::bar()" << std::endl;
}

void A<std::string>::foo(const std::string &value) const
{
    std::cout << "A<std::string>::foo(" << value << ")" << std::endl;
}

#ifndef skip_duplicates
void A<std::string>::bar() const
{
    std::cout << "A<std::string>::bar()" << std::endl;
}
#endif // skip_duplicates

#endif // A_IMPL_HXX

そして今、テストプログラム:

// test.cxx

//#define skip_duplicates
//#define short_declaration
#include "a_impl.hxx"

int main(void)
{
    A<int>         obj1;
    A<std::string> obj2;
    int         value1(1);
    std::string value2("baz");

    obj1.foo(value1);
    obj1.bar();

    obj2.foo(value2);
    obj2.bar();

    return 0;
}

このようにコンパイルすると、(typeidの実装に対して)期待される出力が得られます。

A<T=i>::foo(1)
A<T=i>::bar()
A<std::string>::foo(baz)
A<std::string>::bar()

しかし、もちろん、どちらか、skip_duplicatesまたはshort_declaration私の例でも有効にする方法が欲しいです。やや似たような質問に対してecatmurは、クラス全体を指定する必要があるため、少なくとも定義short_declarationは機能しないと回答しました。

大きなオブジェクトを引数として取る可能性のあるメソッドを使用してクラステンプレートを作成する問題を他の人がどのように処理しますか?

4

2 に答える 2

2

重複を基本クラスに抽出できます。

template<typename T>
struct Base{
    void Bar()
    {
        std::cout << "A<T=" << typeid(T).name() << ">::bar()" << std::endl;
    }

protected:
    ~Base(){}
    template<typename U>
    void DoFoo(U value)
    {
        std::cout << "A<T=" << typeid(T).name() << ">::foo(" << value << ")"
        << std::endl;
    }
};

template<typename T>
struct A : Base<T> {
    void Foo(T value)
    {
        DoFoo(value);
    }
};

template<>
struct A<std::string> : Base<std::string> {
    void Foo(const std::string& value)
    {
        DoFoo(value);
    }
};
于 2012-12-11T12:39:38.427 に答える
0

hansmaadによる回答とYakkによるコメントに基づいて、私が行う解決策は次のとおりだと思います。

// a.hxx
#ifndef A_HXX
#define A_HXX

template<typename T, typename U=T>
struct Abase
{
    void foo(U value) const;
    void bar() const;
};

template<typename T>
struct A : Abase<T> { };

#include <string>

template<>
struct A<std::string> : Abase<std::string, const std::string &> { };

#endif // A_HXX

そしてこの実装:

// a_impl.hxx
#ifndef A_IMPL_HXX
#define A_IMPL_HXX

#include "a.hxx"
#include <iostream>
#include <typeinfo>

template<typename T, typename U>
void Abase<T, U>::foo(U value) const
{
    std::cout << "A<T=" << typeid(T).name() << ",U=" << typeid(U).name()
        << ">::foo(" << value << "): &value=" << int(&value) << std::endl;
}

template<typename T, typename U>
void Abase<T, U>::bar() const
{
    std::cout << "A<T=" << typeid(T).name() << ",U=" << typeid(U).name()
        << ">::bar()" << std::endl;
}

#endif // A_IMPL_HXX

テストプログラムはそのままにすることも、次のような追加の行を取得することもできます。

//...
    std::cout << "&value=" << int(&value1) << std::endl;
//...
    std::cout << "&value=" << int(&value2) << std::endl;
//...

回答と提案の両方に感謝します!

于 2012-12-11T14:59:30.630 に答える