Unë jam duke bërë disa metaprogramime shabllone që përfshijnë tregues funksionesh. Për shkak se llojet e funksioneve për treguesit e funksionit jo-anëtar dhe anëtarë janë të ndryshëm, unë po përpiqem të specializohem midis të dyjave. Për më tepër, unë dua që treguesi i funksionit të jepet si një argument shabllon jo-tip në vend të një parametër të një funksioni në strukturë. Deri tani ja çfarë kam tentuar:
template <typename T, T>
struct register_method;
template <typename R, typename... Args>
struct register_method<R(Args...), R (*method)(Args...)>
{
static R invoke(Args&&... params)
{
return (*method)(std::forward<Args>(params)...);
}
};
template <typename T, typename R, typename... Args>
struct register_method<R(Args...), R (T::*method)(Args...)>
{
static R invoke(T* instance, Args&&... params)
{
return (instance->*method)(std::forward<Args>(params)...);
}
};
Megjithatë kjo nuk arrin të përpilohet (këtu është vetëm gabimi i parë):
prog.cc:14:48: error: 'Args' does not refer to a value
struct register_method<R(Args...), R (*method)(Args...)>
^
prog.cc:13:35: note: declared here
template <typename R, typename... Args>
^
Nuk jam vërtet i sigurt se çfarë po përpiqet të më thotë. Qëllimi im është të përdor këto objekte si kjo:
void the_func(float val)
{
std::cout << "the_func called: " << val << "\n";
}
int main()
{
register_method<decltype(&the_func), &the_func>::invoke(50.f);
}
Si mund ta bëj këtë të funksionojë? Nëse ka një mundësi për të thjeshtuar, kjo do të ishte gjithashtu e mrekullueshme (për shembull, nëse mund të shpëtoj duke kaluar vetëm treguesin e funksionit tek shablloni në vend që të bëj gjithashtu një decltype
, i cili duhet të zvogëlojë pllakën e bojlerit.
EDIT: Gjithashtu dua të shtoj se arsyeja që unë kam nevojë për specializime të veçanta për funksionet jo-anëtare dhe ato anëtare shtrihet përtej vetëm llojeve të funksioneve që janë të ndryshme. Ekziston një gjendje statike midis të dyve që është e ndryshme, për shkak të rregullave të biznesit që unë i bashkangjit llojeve të ndryshme të funksioneve. I kam lënë jashtë këto detaje këtu për ta mbajtur pyetjen të thjeshtë.
P
përsëri përinvoke()
, unë thjesht përdorArgs&&... params
dhe funksionon pa deklaruar argumente shabllone për funksionin statik 24.10.2019void foo(int)
. AtëherëArgs
ështëint
, dheArgs&&... params
ështëint &¶ms
. Pra, kalimi i një lvlere, p.sh.int x = 1; ...::invoke(x);
nuk do të funksionojë. 24.10.2019Args&&...
përfaqëson një referencë universale, kështu që me të vërtetë do të hynte siint& params
, mendoj. 25.10.2019int ¶ms
, nëseArgs
disi ishteint &
. PorArgs
është tashmëint
. Që një referencë të jetë përcjellëse (aka universale), duhet të lini përpiluesin të deduktojë llojin e parametrit. 25.10.2019