我不知道这是否可行,但这是我想要实现的:在模板化的类中,我想使用模板参数的命名空间。
例如。
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
值提供专用的实现,同时我也希望避免传递所有类型,如Type1
和{{ 1}}作为模板参数,因为我可能有很多。
这可能吗?
该项目基于C ++ 3,欢迎任何提升解决方案。
更新
作为模板参数TypeN
本身与任何P
参数完全相同,这可能是正确的方法:
TypeN
答案 0 :(得分: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 ...
),而不需要。
答案 1 :(得分: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)
答案 2 :(得分: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特性(即decltype
和declval
)。出于某种原因,我没有设法让代码与result_of
一起使用,它存在于Boost中(可能有人可以解释为什么带有result_of
的代码无法编译?)。