我已经看到了一些使用模板模板参数(即模板作为参数的模板)来进行基于策略的类设计的C++示例.这种技术有什么其他用途?
从本质上讲,我希望自动像功能的建立std::make_pair,std::bind1st并且std::mem_fun,使不必编写为每个模板类类型不同的功能,你可以编写处理所有情况下,一旦一个可变参数模板模板功能.这个函数的用法如下:
make<std::pair>(1, 2); // equivalent to std::make_pair(1, 2)
make<std::binder2nd>(&foo, 3); // equivalent to std::bind2nd(&foo, 3);
Run Code Online (Sandbox Code Playgroud)
有可能写这个功能make吗?我试过这个,但它在GCC 4.5或4.6中不起作用:
template <template <typename...> class TemplateClass, typename... Args>
TemplateClass<Args...> make(Args&&... args)
{
return TemplateClass<Args...>(std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)
如果我试着打电话(例如)make<std::pair>(1, 2)我就得到
error: no matching function for call to 'make(int, int)'
Run Code Online (Sandbox Code Playgroud)
我在这里的语法错了吗?
或者这是对的,海湾合作委员会是错的吗?
或者这在C++ 0x中根本不可能?
[编辑]
建议N2555似乎表明这是允许的,海湾合作委员会声称已在GCC4.4中实施.
我想知道是否可以编写一个模板函数,可以将任何其他任意模板作为参数并正确匹配模板名称(即不仅仅是结果类).我所知道的工作是:
template<template<typename ...> class TemplateT, typename... TemplateP>
void f(const TemplateT<TemplateP...>& param);
Run Code Online (Sandbox Code Playgroud)
这将匹配例如用于f(std::vector<int>())或f(std::list<int>())但不会对工作f(std::array<int, 3>()),作为第二个参数是一个size_t无类型.
现在我想我可以做一些疯狂的事情:
template<template<typename ...> class TemplateT, size... Sizes, typename... TemplateP>
void f(const TemplateT<Sizes..., TemplateP...>& param);
Run Code Online (Sandbox Code Playgroud)
希望编译器能够正确地将TemplateP省略号或Sizes省略号导出为空.但它不仅难看,它仍然适用于采用任何类型或size_t参数的模板.它仍然不会匹配任意模板,例如bool参数.
对于重载方法也是如此:
template<template<typename ...> class TemplateT, typename... TemplateP>
void f(const TemplateT<TemplateP...>& param);
template<template<typename ...> class TemplateT, size... Sizes>
void f(const TemplateT<Sizes...>& param);
Run Code Online (Sandbox Code Playgroud)
此外,这种方法不会"工作,如果我们想混size_t和typenames.那么匹配任何内容所需要的就是这样的东西,其中对省略号中允许的内容没有任何限制:
template<template<...> class TemplateT, ... Anything>
void f(const TemplateT<Anything...>& param);
Run Code Online (Sandbox Code Playgroud)
该语法不起作用,但也许还有其他语法来定义这样的东西? …
我有一个带有模板模板参数的类模板,我想将此参数(即其所有特化)声明为friend.但我找不到正确的语法.
template <template <class> class T>
struct Foo {
template <class U>
friend T; // "C++ requires a type specifier for all declarations"
template <class U>
friend struct T; // "declaration of 'T' shadows template parameter"
template <class U>
friend struct T<U>; // "cannot specialize a template template parameter"
pretty<please>
lets(be) friends T; // Compiler shook its standard output in pity
};
Run Code Online (Sandbox Code Playgroud)
如何将模板模板参数声明为friend?
每个allocator类必须具有类似于以下内容的接口:
template<class T>
class allocator
{
...
template<class Other>
struct rebind { typedef allocator<Other> other; };
};
Run Code Online (Sandbox Code Playgroud)
使用分配器的类做了多余的事情:
template<class T, class Alloc = std::allocator<T> >
class vector { ... };
Run Code Online (Sandbox Code Playgroud)
但为什么这有必要呢?
换句话说,他们不能只是说:
template<class T>
class allocator { ... };
template<class T, template<class> class Alloc = std::allocator>
class vector { ... };
Run Code Online (Sandbox Code Playgroud)
哪个更优雅,更少冗余,(在某些类似的情况下)可能更安全?
他们为什么要走这rebind条路,这也会造成更多的冗余(即你要说T两次)?
(类似的问题char_traits和其他问题......尽管它们并非都有rebind,但它们仍然可以从模板模板参数中受益.)
但是,如果您需要多于1个模板参数,这将无效!
实际上,它运作得很好!
template<unsigned int PoolSize>
struct pool
{
template<class T>
struct allocator
{
T pool[PoolSize];
... …Run Code Online (Sandbox Code Playgroud) 考虑一下这个C++ 11程序:
#include <iostream>
template <class A, class B = char> struct Cont {
Cont () { std::cout << sizeof(B); }
};
template <template<class, class = int> class C, class E> class Wrap1
{
C<E> ce;
};
template <template<class, class = int> class C, class... E> class Wrap2
{
C<E...> ce;
};
int main ()
{
Wrap1<Cont, void> w1;
Wrap2<Cont, void> w2;
}
Run Code Online (Sandbox Code Playgroud)
使用gcc或clang编译时,输出为41.
这种行为是否符合标准?凡究竟该标准规定它(对于Wrap1和Wrap2)?
这个问题部分受到另一个问题的启发.
以下代码无法编译......
namespace {
template<typename T, template<typename> class D>
struct Base {
Base(const T& _t) : t(_t) { }
T t;
};
template<typename T>
struct Derived : Base<T, Derived> {
Derived(const T& _t) : Base<T, Derived>(_t) { }
};
}
int main(int argc, char* argv[]) {
Derived<int> d(1);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
该行有一个编译错误 - Derived(const T& _t) : Base<T, Derived>(_t) { }
错误C3200''anonymous-namespace':: Derived':模板参数'D'的模板参数无效,需要一个类模板
如果我提供任何其他具有模板参数而不是Derived本身的类,则此方法有效
template<typename T>
struct Other {
};
template<typename T>
struct Derived : Base<T, Other> {
Derived(const T& _t) …Run Code Online (Sandbox Code Playgroud) 我想知道是否有可能拥有具有以下行为的代码:
int main()
{
func<vector>(/*some arguments*/);
}
Run Code Online (Sandbox Code Playgroud)
也就是说,我希望用户能够指定容器而不指定其操作的类型.
例如,可能定义的某些(元)代码(不适用于上述代码)func将如下所示:
template<typename ContainerType>
int func(/*some parameters*/)
{
ContainerType<int> some_container;
/*
operate on some_container here
*/
return find_value(some_container);
}
Run Code Online (Sandbox Code Playgroud) 假设我有一些模板类定义如下
template<template<class>class...>
struct my_class;
template<class>
struct define_template{
template<class>
class type;
};
Run Code Online (Sandbox Code Playgroud)
我需要定义一个别名模板,将define_template :: type替换为my_class,因此对于三个类我可以这样做
template<class A, class B, class C>
using my_alias = my_class< define_template<A>::template type,
define_template<B>::template type,
define_template<C>::template type>;
Run Code Online (Sandbox Code Playgroud)
我无法解决语法为可变参数模板做这样的事情
template<class... T>
using new_class = my_class<define_template<T>::template type...>;
Run Code Online (Sandbox Code Playgroud)
这给了我一个错误"参数包没有扩展'...'
有人知道正确的synax吗?
从下面的评论中,它编译成clang,我使用gcc 4.8.2通过Cygwin.
昨天我问了一个关于模板模板参数的扣除指南使用保证的问题.当Barry改变了对代码标准符合性确认的答案时,我感到非常惊讶.令我惊讶的是,实际上并不是因为扣除指南可以应用于模板模板参数,而是来自符合此合规性的标准部分,即[temp.param]/3:
标识符不遵循省略号的类型参数将其标识符定义为模板声明范围内的typedef-name(如果未声明
template)或template-name(如果声明template).
加上[temp.deduct.guide]/1和simple-template-id规则可以创建一个接受任何模板的通用推理指南.
#include <string>
template <class T>
struct Foo {
Foo(T) { }
};
template <template <class> class TT>
TT(const char *) -> TT<std::string>;
int main() {
Foo foo("abc");
}
Run Code Online (Sandbox Code Playgroud)
代码导致gcc因内部错误而崩溃,并导致clang中的编译错误.说实话,我并不是说代码应该在C++中实际允许,但认为当前的措辞确实使它符合要求.我错过了一些不允许代码的重要规则吗?
c++ template-templates language-lawyer template-argument-deduction c++17