具有专用和非专用类型的模板重载
Template overloading with specialized and unspecialized type
template < typename...dummy >
class wrapper;
template < typename TYPE >
class wrapper < TYPE > {};
template < template < typename... > class TYPE, typename... PARAMS >
class wrapper < TYPE < PARAMS... > > {};
template < typename >
class templated_class {};
class normal_class {};
typedef wrapper < normal_class > normal_wrapper;
typedef wrapper < templated_class, int > templated_wrapper;
编译上述内容显然会导致错误
'templated_class': class template ( not specialized ) cannot be a template argument for 'dummy', an actual type was expected
如何使其工作,以便wrapper
可以接受normal_class
和templated_class
作为第一个参数?我觉得有一个简单的方法,但我看不到它,因为我太执着于这个问题了。
我不能只写的原因
typedef wrapper < templated_class < int > > templated_wrapper;
是因为 typedef 是由可变参数宏创建的,该宏 - 出于 MCVE 目的剥离 - 如下所示:
#define first_va(f,...) f
#define createwrapper(...)
typedef wrapper < __VA_ARGS__ > first_va(__VA_ARGS__)_wrapper;
createwrapper(normal_class)
createwrapper(templated_class,int)
而且我不知道如何执行预处理器魔法以在 <>
中的第一个参数之后括起所有参数,如果可能的话。
使用模板或宏的解决方案对我来说都是可以接受的,尽管我更喜欢模板解决方案。
#define createwrapper_single(f)
typedef wrapper<f> f##_wrapper;
#define createwrapper_multiple(f, ...)
typedef wrapper<f<__VA_ARGS__> > f##_wrapper;
#define pick_createwrapper(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, NAME, ...) NAME
#define createwrapper(...)
pick_createwrapper(__VA_ARGS__, createwrapper_multiple, createwrapper_multiple,
createwrapper_multiple, createwrapper_multiple, createwrapper_multiple,
createwrapper_multiple, createwrapper_multiple, createwrapper_multiple,
createwrapper_multiple, createwrapper_single, something_is_wrong_if_this_is_used)(__VA_ARGS__)
演示。显然,正如所写的那样,如果您疯狂地编写一个包含 9 个以上参数的模板,这将中断,但如有必要,您可以将其扩展到任意数量的参数。
或者,您可以使用decltype
和重载函数:
template <template < typename... > class T, typename... params>
wrapper<T<params...>> wrapper_helper();
template <typename T>
wrapper<T> wrapper_helper();
#define first_va(f,...) f
#define PASTE2(x, y) x##y
#define PASTE(x, y) PASTE2(x,y)
#define createwrapper(...)
typedef decltype(wrapper_helper< __VA_ARGS__ >())
PASTE(first_va(__VA_ARGS__,_blank), _wrapper);
演示。
你不能这样。定义具有简单typename
类型(不是模板也不是值(的所有参数的模板后,所有专用化都必须使用类型作为实际模板参数。相反,如果参数是模板,则相应的参数将始终是任何专用化的模板。也就是说,类模板没有重载。
您正在尝试做不可能的事情,因为您将部分专业化中存在的两个括号分隔列表混淆了。我想我会在这里用代码现场演示来解释它。
#include <iostream>
template <typename...> // <--- to instantiate, say `wrapper<whatever list of types>`
struct wrapper
{
static void foo() {
std::cout << "generic" << std::endl;
}
};
template<typename T>
struct wrapper<T> // <--- to instantiate, say `wrapper<sometype>`
{
static void foo() {
std::cout << "one argument" << std::endl;
}
};
// just an illustration
template <typename T> // <--------------------------------------------------+
struct wrapper <int, double, T> // <--- to instantiate, use this list of arguments |
{ // not this one -----------------------------+
// that is, say `wrapper<int, double, sometype>`
// not `wrapper<sometype>`
static void foo() {
std::cout << "three arguments (int, double, something)" << std::endl;
}
};
template <template<typename ...> class T, // <-----------------------------------------+
typename K> // |
struct wrapper<T<K>> // <--- to instantiate, use this list of arguments |
{ // not this one ------------------------------+
// that is, say `wrapper<sometemplate<sometype>>`
static void foo() {
std::cout << "the template thingy" << std::endl;
}
};
template <typename> class X {};
int main ()
{
wrapper<int, int>::foo();
wrapper<int>::foo();
wrapper<int, double, X<int>>::foo();
wrapper<X<int>>::foo();
}
相关文章:
- 使用类指针重载C++命名空间函数模板专用化替代方法?
- 模板专用化与函数重载
- C++函数模板专用化和重载
- 函数模板重载 - 部分专用化
- 专用和/或重载具有可变参数的成员函数模板
- 模板专用类之间的构造函数重载
- 通过重载实现部分模板专用化
- 如何为模板类的所有实例专用化或重载全局模板函数
- 对于重载函数,为父实例和子实例调用专用版本
- 部分专用结构与重载函数模板
- 部分模板专用化可能不适用于函数,但重载不是一回事吗?
- 运算符<<重载时无法访问专用成员(指定指针)
- 为什么重载优先于ADL中的显式专用化
- 重载特定模板专用化的成员函数
- 运算符重载和模板专用化
- 以下语句是函数重载还是函数部分专用化
- 函数模板重载 - 专用化
- 带有重载的显式模板函数专用化:为什么要这样做
- 重载运算符'<<'(左移)的显式专用化
- 在模板专用化和重载 C++ 方面没有预期的歧义