有没有人曾经使用指针/引用/指向成员(非类型)模板参数?
我不知道任何(理智/真实世界)场景,其中C++特性应该被用作最佳实践.
演示功能(用于指针):
template <int* Pointer> struct SomeStruct {};
int someGlobal = 5;
SomeStruct<&someGlobal> someStruct; // legal c++ code, what's the use?
Run Code Online (Sandbox Code Playgroud)
任何启蒙都将不胜感激!
Syn*_*xis 11
指针功能:
指向成员函数和指向函数的非类型参数对某些代表非常有用.它允许您快速制作代表.
例如:
#include <iostream>
struct CallIntDelegate
{
virtual void operator()(int i) const = 0;
};
template<typename O, void (O::*func)(int)>
struct IntCaller : public CallIntDelegate
{
IntCaller(O* obj) : object(obj) {}
void operator()(int i) const
{
// This line can easily optimized by the compiler
// in object->func(i) (= normal function call, not pointer-to-member call)
// Pointer-to-member calls are slower than regular function calls
(object->*func)(i);
}
private:
O* object;
};
void set(const CallIntDelegate& setValue)
{
setValue(42);
}
class test
{
public:
void printAnswer(int i)
{
std::cout << "The answer is " << 2 * i << "\n";
}
};
int main()
{
test obj;
set(IntCaller<test,&test::printAnswer>(&obj));
}
Run Code Online (Sandbox Code Playgroud)
指向数据的指针:
您可以使用此类非类型参数来扩展变量的可见性.
例如,如果您正在编写反射库(可能对脚本非常有用),使用宏让用户为库声明其类,您可能希望将所有数据存储在复杂的结构中(这可能会随着时间的推移而变化) ),并希望有一些句柄来使用它.
例:
#include <iostream>
#include <memory>
struct complex_struct
{
void (*doSmth)();
};
struct complex_struct_handle
{
// functions
virtual void doSmth() = 0;
};
template<complex_struct* S>
struct csh_imp : public complex_struct_handle
{
// implement function using S
void doSmth()
{
// Optimization: simple pointer-to-member call,
// instead of:
// retrieve pointer-to-member, then call it.
// And I think it can even be more optimized by the compiler.
S->doSmth();
}
};
class test
{
public:
/* This function is generated by some macros
The static variable is not made at class scope
because the initialization of static class variables
have to be done at namespace scope.
IE:
class blah
{
SOME_MACRO(params)
};
instead of:
class blah
{
SOME_MACRO1(params)
};
SOME_MACRO2(blah,other_params);
The pointer-to-data template parameter allows the variable
to be used outside of the function.
*/
std::auto_ptr<complex_struct_handle> getHandle() const
{
static complex_struct myStruct = { &test::print };
return std::auto_ptr<complex_struct_handle>(new csh_imp<&myStruct>());
}
static void print()
{
std::cout << "print 42!\n";
}
};
int main()
{
test obj;
obj.getHandle()->doSmth();
}
Run Code Online (Sandbox Code Playgroud)
很抱歉的auto_ptr,shared_ptr可既不在键盘也不Ideone.
实例.
指向成员的指针的情况与指向数据或引用的指针大不相同.
如果要指定要调用的成员函数(或要访问的数据成员)但是您不希望将对象放在特定层次结构中(否则虚拟方法通常就足够了),指向成员作为模板参数的指针会很有用.
例如:
#include <stdio.h>
struct Button
{
virtual ~Button() {}
virtual void click() = 0;
};
template<class Receiver, void (Receiver::*action)()>
struct GuiButton : Button
{
Receiver *receiver;
GuiButton(Receiver *receiver) : receiver(receiver) { }
void click() { (receiver->*action)(); }
};
// Note that Foo knows nothing about the gui library
struct Foo
{
void Action1() { puts("Action 1\n"); }
};
int main()
{
Foo foo;
Button *btn = new GuiButton<Foo, &Foo::Action1>(&foo);
btn->click();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果您不想为访问支付额外的运行时价格,则指针或对全局对象的引用可能很有用,因为模板实例化将使用常量(加载时解析)地址访问指定对象,而不是像它那样的间接访问将使用常规指针或引用发生.然而,要支付的价格是每个对象的新模板实例化,实际上很难想到一个有用的真实案例.