当模板的功能不同时C++模板
C++ template when the template's function is not the same
现在我有了一个模板类
template <class T>
class b
{
void someFunc() {
T t;
t.setB();
}
};
我知道模板T只会被实例化为2个类。
class D
{
public:
void setB();
};
class R
{
public:
void SetB();
};
可以看到,D类的函数名setB与R类的函数名setB不一样。所以在模板类b中,我不能只使用setB。如果我不能修改D或R,有什么方法吗?我可以在模板类中添加一些包装器或技巧来解决这个问题吗? 也许trait类可以帮助你:
struct Lower {};
struct Upper {};
// trait for most cases
template <typename T>
struct the_trait {
typedef Lower Type;
};
// trait for special cases
template <>
struct the_trait<R> {
typedef Upper Type;
};
template <class T>
class b {
public:
void foo() {
foo_dispatch(typename the_trait<T>::Type());
}
private:
void foo_dispatch(Lower) {
T t;
t.setB();
}
void foo_dispatch(Upper) {
T t;
t.SetB();
}
};
正如@Arunmu所指出的,这种技术也被称为标签调度。
您可以为具有不同语义的类专门化您的模板:
template<>
class b<R>
{
void doWork() {
R obj;
obj.SetB();
// or R::SetB() if it was a static method.
}
};
您还可以使用SFINAE检查函数是否存在,而不是使用自编程特征。
如果你想切换被调用的方法,每个类中必须有一个。如果检查发现多个测试方法,我提供的方法将不起作用!
下面的例子是为c++ 14编写的,但如果你用自己实现的函数替换新的库函数(当然不方便),也可以在c++03中使用
测试类has_Foo和has_Bar也可以嵌入到预处理器宏中,但我将其展开以使其更易于阅读。
它是如何工作的以及为什么需要更多的中间步骤在评论中解释了。看下面!
#include <iostream>
// First we write two classes as example. Both classes represents
// external code which you could NOT modify, so you need an
// adapter to use it from your code.
class A
{
public:
void Foo() { std::cout << "A::Foo" << std::endl; }
};
class B
{
public:
void Bar() { std::cout << "B::Bar" << std::endl; }
};
// To benefit from SFINAE we need two helper classes which provide
// a simple test functionality. The solution is quite easy...
// we try to get the return value of the function we search for and
// create a pointer from it and set it to default value nullptr.
// if this works the overloaded method `test` returns the data type
// one. If the first test function will not fit, we cat with ... all
// other parameters which results in getting data type two.
// After that we can setup an enum which evaluates `value` to
// boolean true or false regarding to the comparison function.
template <typename T>
class has_Foo
{
using one = char;
using two = struct { char a; char b;};
template <typename C> static one test( typename std::remove_reference<decltype(std::declval<C>().Foo())>::type* );
template <typename C> static two test( ... ) ;
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
enum { Yes = sizeof(test<T>(0)) == sizeof(one) };
enum { No = !Yes };
};
template <typename T>
class has_Bar
{
using one = char;
using two = struct { char a; char b;};
template <typename C> static one test( typename std::remove_reference<decltype(std::declval<C>().Bar())>::type* );
template <typename C> static two test( ... ) ;
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
enum { Yes = sizeof(test<T>(0)) == sizeof(one) };
enum { No = !Yes };
};
// Now in your adapter class you can use the test functions
// to find out which function exists. If your class
// contains a Foo function the first one compiles and if the
// the class contains a Bar function the second one fits. SFINAE
// disable the rest.
// We need a call helper here because SFINAE only
// fails "soft" if the template parameter can deduced from the
// given parameters to the call itself. So the method
// Call forwards the type to test "T" to the helper method as
// as explicit parameter. Thats it!
template <typename T>
class X: public T
{
public:
template < typename N, std::enable_if_t< has_Foo<N>::value>* = nullptr>
void Call_Helper() { this->Foo(); }
template < typename N, std::enable_if_t< has_Bar<N>::value>* = nullptr>
void Call_Helper() { this->Bar(); }
void Call() { Call_Helper<T>(); }
};
int main()
{
X<A> xa;
X<B> xb;
xa.Call();
xb.Call();
}
相关文章:
- .cpp和.h文件中的模板专用化声明
- C++模板来检查友元函数的存在
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- 部分定义/别名模板模板参数
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 如何在c++中为模板函数实例创建快捷方式
- 使用C++中的模板和运算符重载执行矩阵运算
- 有人能分解一下这个c++模板的语法吗
- 如何在c++17中制作一个模板包装器/装饰器
- 模板化建造师专业化
- 调用专用模板时出错"no matching function for call to [...]"
- 模板元程序查找相似的连续类型名称
- 如何在C++20中创建模板别名的推导指南
- 没有名称的C++模板参数
- 具有重复类型的C++可变模板
- 如何将enable-if与模板参数和参数包一起使用
- 没有用于初始化C++中的变量模板的匹配构造函数