8

それが実現可能かどうかはまったくわかりませんが、これを実現したいと思います。テンプレート化されたクラスでは、テンプレートパラメータの名前空間を使用したいと思います。

例えば。

template<class P>
class Foo
{
    public:
        Foo();
        virtual ~Foo();

        void doSomething(P&);
        void doSomethingElse();

    protected:
        // There I'm hardcoding "namespace1" but that's what I'd like to 
        // be possibly dynamic 
        // (I'm assuming template parameter P = namespace1::Type)
        void method1(namespace1::Type1&);
        ...
        void methodN(namespace1::TypeN&);
}

// Again, supposing P == namespace1::Type then I want to be using namespace1 
// everywhere in the implementation...
using namespace namespace1;

template<class P>
void Foo<P>::doSomething(P& parameter)
{
    ...
    Type1 type1 = P.getType1(); // There namespace1::Type1 is returned !!
    method1(type1);
    ...
}

template<class P>
void Foo<P>::doSomethingElse()
{
    ...
    TypeN typen; // There I want to instanciate a namespace1::TypeN !!
    ...
}

...

もちろん、テンプレートを特殊化して、すべての可能な値に専用の実装を提供したくはありません。また、テンプレートパラメータPのようなすべてのタイプを渡すことは避けたいので、それらがたくさんある可能性があります。Type1TypeN

それは可能ですか?

プロジェクトはC++3ベースであり、ブーストソリューションは大歓迎です。

アップデート

テンプレートパラメータP自体は他のパラメータとまったく同じTypeNであるため、これは正しいアプローチである可能性があります。

template<typename NAMESPACE>
class Foo
{
    typedef typename NAMESPACE::Parameter MyParameter; 
    typedef typename NAMESPACE::Type1 MyType1; 
    typedef typename NAMESPACE::Type1 MyTypeN; 
    ...
}
4

3 に答える 3

5

はいといいえ。

はい、一般的に特性システムを使用して、プライマリ タイプからセカンダリ タイプを推測することは可能です。

template <typename T> struct Trait { typedef typename T::Secondary Secondary; };

template <typename X>
struct Foo {
    typedef typename Trait<X>::Secondary Secondary;

    void foo(Secondary const& s);
};

いいえ、名前空間を推測できないため、使用できません。ただし、クラス内でローカル エイリアス ( typedef ...) を使用することで、その必要がないことに注意してください。

于 2013-02-22T14:27:28.923 に答える
0

いいえ、それは不可能ですが、醜いマクロ ファイルを使用することはできます。

//my_class.inl
template<TYPE_ARG>
struct my_class_t<TYPE_ARG>
{
   foo()
   {
      NS_ARG::bar();
   }
}

//my.h
template<class T>
struct my_class_t{};

#define TYPE_ARG T1
#define NS_ARG std
#include "my_class.inl"

#define TYPE_ARG T2
#define NS_ARG boost
#include "my_class.inl"

#undef TYPE_ARG
#undef NS_ARG

そうすれば、さまざまな名前空間のクラスの特殊化を自動化できます。これは本当に必要ですか?:o)

于 2013-02-22T14:20:51.467 に答える
0

必要なすべての型をリストする各名前空間内に構造を追加する場合は、ADL を使用して、テンプレート パラメーターに応じてこの構造を取得できます。

#include <iostream>
#include <utility>

namespace Foo_ns
{
    struct T1
    {
        static void m() { std::cout << "Foo_ns::T1" << '\n'; }
    };
    struct Foo {};

    // List of all the types you need from this namespace
    struct Types
    {
        typedef Foo_ns::T1 T1;        
    };

    // dummy function needed for ADL        
    Types types(...);
}

namespace Bar_ns
{
    struct T1
    {
        static void m() { std::cout << "Bar_ns::T1" << '\n'; }
    };
    struct Bar {};

    struct Types
    {
        typedef Bar_ns::T1 T1;
    };

    Types types(...);
}

template <typename T>
void callMOnT1(const T &arg)
{
    typedef decltype(types(std::declval<T>())) Types; // ADL kicks in
    //typedef typename std::result_of<types(T)>::type Types;
    Types::T1::m();
}

int main()
{
    callMOnT1((Bar_ns::Bar())); // Bar_ns::T1
    callMOnT1((Foo_ns::Foo())); // Foo_ns::T1
}

残念ながら、このソリューションではいくつかの C++11 機能 (つまりdecltypedeclval) を使用しています。何らかの理由で、result_ofBoost に存在する でコードを動作させることができませんでした (おそらく、 のコードがresult_ofコンパイルされない理由を誰かが説明できますか?)。

于 2013-02-22T14:46:26.883 に答える