最后编辑
我有一个带模板的功能:
template <template <typename ...> class P, typename ... Args>
void f(const P<Args...> &p)
{
std::cout << "Template with " << sizeof...(Args) << " parameters!\n";
}
到目前为止我测试过的任何模板都能很好用:
f(std::valarray<int>{}); // Prints: "Template with 1 parameters!"
f(std::pair<char, char>{}); // Prints: "Template with 2 parameters!"
f(std::set<float>{}); // Prints: "Template with 3 parameters!"
f(std::map<int, int>{}); // Prints: "Template with 4 parameters!"
但是,让我们假设我想专门化模板,当它带有两个参数的模板时,下面的代码不起作用:
template <>
void f<template <typename, typename> class P, typename A, typename B>(const P<A, B> &p)
{
std::cout << "Special case!\n";
}
parse error in template argument list
void f<template <typename, typename> class P, typename A, typename B>(const P<Args...> &p) { std::cout << "Template with " << sizeof...(Args) << " parameters!\n"; }
^
'P' does not name a type
void f<template <typename, typename> class P, typename A, typename B>(const P<Args...> &p) { std::cout << "Template with " << sizeof...(Args) << " parameters!\n"; }
^
expected ',' or '...' before '<' token
void f<template <typename, typename> class P, typename A, typename B>(const P<Args...> &p) { std::cout << "Template with " << sizeof...(Args) << " parameters!\n"; }
^
template-id 'f<<expression error> >' for 'void f(int)' does not match any template declaration
void f<template <typename, typename> class P, typename A, typename B>(const P<Args...> &p) { std::cout << "Template with " << sizeof...(Args) << " parameters!\n"; }
AFAIK使用其他类型的模板参数非常简单:
// Type parameter
template <typename TYPE>
void f(TYPE) { std::cout << "Type!\n"; }
// Non-type parameter
template <int VALUE>
void f() { std::cout << "Value " << VALUE << "!\n"; }
// Type parameter specialization
template <>
void f(float) { std::cout << "Special type case!\n"; }
// Non-type parameter specialization
template <>
void f<666>() { static_assert(false, "Forbidden number!"); }
如何使用模板模板模板实现此功能?
正如orlp和angew指出的那样,功能模板不能部分专业化,所以我应该坚持使用对象模板,here is my attempt:
template <template <typename ...> class P, typename ... Args>
struct c
{
using type = P<Args...>;
const std::size_t count = sizeof...(Args);
void f(const type &t)
{
std::cout << "Template with " << sizeof...(Args) << " parameters!\n";
}
};
template <template <typename, typename> class P, typename A, typename B>
struct c<P, A, B>
{
using type = P<A, B>;
void f(const type &t)
{
std::cout << "Spezialized 2 parameters!\n";
}
};
有效:
c<std::valarray, int> c_valarray_int;
c<std::pair, int, char> c_pair_int_char;
c<std::vector, int, std::allocator<int>> c_vector_int;
c<std::map, int, int> c_map_int_int;
c_valarray_int.f({}); // Prints: "Template with 1 parameters!"
c_pair_int_char.f({}); // Prints: "Spezialized with 2 parameters!"
c_vector_int.f({}); // Prints: "Spezialized with 2 parameters!"
c_map_int_int.f({}); // Prints: "Template with 2 parameters!" (expected)
但是现在,我应该指定所有参数,而不是让编译器猜测整个事情,那......这不是悲剧。
答案 0 :(得分:4)
您正在尝试使用两个模板参数任何模板的部分功能模板专精化专业化。这在C ++中是不允许的。功能模板不能部分专业化。
以另一种方式看待:您为tempalte类型参数和模板非类型参数显示的显式特化使用具体参数。要明确专门化您的功能模板,您可以执行以下操作:
template <>
void f<std::pair, int, double>(const std::pair<int, double> &p)
{
std::cout << "Special case!\n";
}
在原始代码中,P
,A
和B
仍然是&#34;未绑定&#34; - 他们的参数,而不是参数。显式专业化不能有模板参数;必须将专用主模板的所有模板参数绑定到该专业化提供的具体参数。
要解决您的编辑问题:您仍然可以使用参数推导保留功能模板界面,并简单地将调用转发给(可能是部分专用的)类模板,如下所示:
template <template <typename ...> class P, typename ... Args>
struct c
{
using type = P<Args...>;
static const std::size_t count = sizeof...(Args);
static void f(const type &t)
{
std::cout << "Template with " << sizeof...(Args) << " parameters!\n";
}
};
template <template <typename, typename> class P, typename A, typename B>
struct c<P, A, B>
{
using type = P<A, B>;
static void f(const type &t)
{
std::cout << "Spezialized 2 parameters!\n";
}
};
template <template <class ...> class P, class... Args>
void f(const P<Args...> &t)
{
c<P, Args...>::f(t);
}
答案 1 :(得分:2)
嗯,做你正在尝试做的事情的正确语法是:
template <template<typename, typename> class P, typename A, typename B>
void f<P, A, B>(const P<A, B> &p) {
std::cout << "Special case!\n";
}
但是,这是部分特化,不允许在功能上使用。您可以使用静态方法将函数转换为类,并使用包装函数调用类的静态方法。