使用模板模板参数的模板参数
Use template parameter of template template parameter
我目前正在使用 C++ 中的 template
s 并卡在 template template parameters
.
假设我有以下 classes:
template<typename T>
struct MyInterface
{
virtual T Foo() = 0;
}
class MyImpl : public MyInterface<int>
{
public:
int Foo() { /*...*/ }
};
template< template<typename T> typename ImplType>
class MyHub
{
public:
static T Foo()
{
ImplType i;
return i.Foo();
}
private:
MyHub() { }
~MyHub() { }
};
本质上我想要一个像 MyHub
这样的 static class
接受 MyInterface
的实现并提供某些 static
方法来使用它们 [=18] =].
然后我尝试使用 MyHub
:
int main()
{
int i = MyHub<MyImpl>::Foo();
return 0;
}
不幸的是,我总是得到一个错误,说类型 T
(属于 MyHub 中的 static T Foo()
)没有命名类型。
我希望它能起作用,因为
- 模板参数
Impl
的模板参数名为T
MyHub
是一个带有一个模板参数的模板化 class 并且包含一个方法 Foo
到目前为止,我在查阅文档和 google 结果后找不到解决方案,所以我希望你们中的一些人能帮助我。
您可以使用 typedef。此外,由于您的实现 classes 不是模板 class,因此不需要模板模板参数。
#include <iostream>
#include <string>
template<typename T>
struct MyInterface
{
virtual T Foo() = 0;
typedef T Type;
};
class MyIntImpl : public MyInterface<int>
{
public:
int Foo() { return 2; }
};
class MyStringImpl : public MyInterface<std::string>
{
public:
std::string Foo() { return "haha"; }
};
template<class ImplType>
class MyHub
{
public:
static typename ImplType::Type Foo()
{
ImplType i;
return i.Foo();
}
private:
MyHub() { }
~MyHub() { }
};
int main()
{
std::cout << MyHub<MyIntImpl>::Foo() << "\n"; // prints 2
std::cout << MyHub<MyStringImpl>::Foo() << "\n"; // print haha
return 0;
}
Here就是一个例子。
STL 使用 value_type 作为模板基础类型 class 的占位符。您也可以为您的解决方案做同样的事情。
template<typename T>
struct MyInterface
{
typedef T value_type;
virtual T Foo() = 0;
}
class MyImpl : public MyInterface<int>
{
public:
int Foo() { /*...*/ }
};
template<typename ImplType>
class MyHub
{
public:
static typename ImplType::value_type Foo()
{
ImplType i;
return i.Foo();
}
private:
MyHub() { }
~MyHub() { }
};
另请注意,在c++14中,typename ImplType::value_type
可以替换为auto
:
static auto Foo()
{
ImplType i;
return i.Foo();
}
模板模板参数的模板参数名称实际上是一个纯粹的文档结构——它们不包含在包含模板的范围内。
这是有充分理由的:在包含的模板中没有他们可以引用的内容。当你有模板模板参数时,你必须传递一个 template 作为参数给它,而不是模板的 instantiation。换句话说,您传递的模板 没有参数 作为参数。
这意味着您的代码完全错误——您使用 MyImpl
作为 MyHub
的参数,但 MyImpl
是 class . MyHub
需要一个 模板, 而不是 class。 [=13 的正确实例化=] 将是 MyHub<MyInterface>
。并不是说在使用 MyInterface
之后没有模板参数;我们传递的是模板本身,而不是它的实例。
Template 模板参数在实践中很少使用。仅当您想使用自己的类型实例化参数模板时才使用它们。所以我希望你的 MyHub
代码能做这样的事情:
template <template <class> class ImplTemplate>
struct MyHub
{
typedef ImplTemplate<SomeMyHub_SpecificType> TheType;
// ... use TheType
};
这似乎不是您想要的。我相信您需要一个普通类型模板参数,并为其 T
提供一个嵌套的 typedef。像这样:
template <class T>
struct MyInterface
{
typedef T ParamType; // Added
virtual T Foo() = 0;
};
template<class ImplType>
class MyHub
{
typedef typename ImplType::ParamType T;
public:
static T Foo()
{
ImplType i;
return i.Foo();
}
private:
MyHub() { }
~MyHub() { }
};
int main()
{
int i = MyHub<MyImpl>::Foo();
return 0;
}
MyImpl
不是 class 模板;所以不能作为 MyInterface
.
的模板参数传递
您可以将 MyInterface
、MyImpl
和 MyHub
class 更改为:
template<typename T>
class MyInterface{
public:
virtual T foo() = 0;
};
class MyImpl: public MyInterface<int>{
public:
using value_type = int;
value_type foo(){ return 1; /* dummy */ }
};
template<typename Impl, typename = std::enable_if_t<std::is_base_of<Impl, MyInterface<typename Impl::value_type>>::value>>
class MyHub{
public:
static auto foo(){
static Impl i;
return i.foo();
}
};
这让您可以像在示例中一样使用它。
在这种情况下,std::is_base_of
检查可能有点不必要;但是,这样你就不会不小心传入另一个不是从 MyInterface
派生的 class 方法 foo()
.
我目前正在使用 C++ 中的 template
s 并卡在 template template parameters
.
假设我有以下 classes:
template<typename T>
struct MyInterface
{
virtual T Foo() = 0;
}
class MyImpl : public MyInterface<int>
{
public:
int Foo() { /*...*/ }
};
template< template<typename T> typename ImplType>
class MyHub
{
public:
static T Foo()
{
ImplType i;
return i.Foo();
}
private:
MyHub() { }
~MyHub() { }
};
本质上我想要一个像 MyHub
这样的 static class
接受 MyInterface
的实现并提供某些 static
方法来使用它们 [=18] =].
然后我尝试使用 MyHub
:
int main()
{
int i = MyHub<MyImpl>::Foo();
return 0;
}
不幸的是,我总是得到一个错误,说类型 T
(属于 MyHub 中的 static T Foo()
)没有命名类型。
我希望它能起作用,因为
- 模板参数
Impl
的模板参数名为T MyHub
是一个带有一个模板参数的模板化 class 并且包含一个方法Foo
到目前为止,我在查阅文档和 google 结果后找不到解决方案,所以我希望你们中的一些人能帮助我。
您可以使用 typedef。此外,由于您的实现 classes 不是模板 class,因此不需要模板模板参数。
#include <iostream>
#include <string>
template<typename T>
struct MyInterface
{
virtual T Foo() = 0;
typedef T Type;
};
class MyIntImpl : public MyInterface<int>
{
public:
int Foo() { return 2; }
};
class MyStringImpl : public MyInterface<std::string>
{
public:
std::string Foo() { return "haha"; }
};
template<class ImplType>
class MyHub
{
public:
static typename ImplType::Type Foo()
{
ImplType i;
return i.Foo();
}
private:
MyHub() { }
~MyHub() { }
};
int main()
{
std::cout << MyHub<MyIntImpl>::Foo() << "\n"; // prints 2
std::cout << MyHub<MyStringImpl>::Foo() << "\n"; // print haha
return 0;
}
Here就是一个例子。
STL 使用 value_type 作为模板基础类型 class 的占位符。您也可以为您的解决方案做同样的事情。
template<typename T>
struct MyInterface
{
typedef T value_type;
virtual T Foo() = 0;
}
class MyImpl : public MyInterface<int>
{
public:
int Foo() { /*...*/ }
};
template<typename ImplType>
class MyHub
{
public:
static typename ImplType::value_type Foo()
{
ImplType i;
return i.Foo();
}
private:
MyHub() { }
~MyHub() { }
};
另请注意,在c++14中,typename ImplType::value_type
可以替换为auto
:
static auto Foo()
{
ImplType i;
return i.Foo();
}
模板模板参数的模板参数名称实际上是一个纯粹的文档结构——它们不包含在包含模板的范围内。
这是有充分理由的:在包含的模板中没有他们可以引用的内容。当你有模板模板参数时,你必须传递一个 template 作为参数给它,而不是模板的 instantiation。换句话说,您传递的模板 没有参数 作为参数。
这意味着您的代码完全错误——您使用 MyImpl
作为 MyHub
的参数,但 MyImpl
是 class . MyHub
需要一个 模板, 而不是 class。 [=13 的正确实例化=] 将是 MyHub<MyInterface>
。并不是说在使用 MyInterface
之后没有模板参数;我们传递的是模板本身,而不是它的实例。
Template 模板参数在实践中很少使用。仅当您想使用自己的类型实例化参数模板时才使用它们。所以我希望你的 MyHub
代码能做这样的事情:
template <template <class> class ImplTemplate>
struct MyHub
{
typedef ImplTemplate<SomeMyHub_SpecificType> TheType;
// ... use TheType
};
这似乎不是您想要的。我相信您需要一个普通类型模板参数,并为其 T
提供一个嵌套的 typedef。像这样:
template <class T>
struct MyInterface
{
typedef T ParamType; // Added
virtual T Foo() = 0;
};
template<class ImplType>
class MyHub
{
typedef typename ImplType::ParamType T;
public:
static T Foo()
{
ImplType i;
return i.Foo();
}
private:
MyHub() { }
~MyHub() { }
};
int main()
{
int i = MyHub<MyImpl>::Foo();
return 0;
}
MyImpl
不是 class 模板;所以不能作为 MyInterface
.
您可以将 MyInterface
、MyImpl
和 MyHub
class 更改为:
template<typename T>
class MyInterface{
public:
virtual T foo() = 0;
};
class MyImpl: public MyInterface<int>{
public:
using value_type = int;
value_type foo(){ return 1; /* dummy */ }
};
template<typename Impl, typename = std::enable_if_t<std::is_base_of<Impl, MyInterface<typename Impl::value_type>>::value>>
class MyHub{
public:
static auto foo(){
static Impl i;
return i.foo();
}
};
这让您可以像在示例中一样使用它。
在这种情况下,std::is_base_of
检查可能有点不必要;但是,这样你就不会不小心传入另一个不是从 MyInterface
派生的 class 方法 foo()
.