考虑一个具有接受指向成员函数的指针的静态方法模板的结构。请注意,当方法的参数之一是实际的指向成员函数的指针时,可以推导出两个模板参数,无论另一个参数是否是nullptr
or not.
请参阅以下代码下面的问题:
struct Checker
{
template <typename T, typename V>
static void Check(
V(T::*getter)(),
void(T::*setter)(V)
);
template <typename T, typename V>
static void CheckDefault(
V(T::*getter)() = nullptr,
void(T::*setter)(V) = nullptr
);
};
struct Test
{
int Value();
void Value(int);
int Getter();
void Setter(int);
};
Checker::CheckDefault(&Test::Value); //1
Checker::CheckDefault(&Test::Value, nullptr); //2
Checker::Check(&Test::Value, nullptr); //3
Checker::CheckDefault(&Test::Getter); //4
Checker::CheckDefault(&Test::Getter, nullptr); //5
Checker::Check(&Test::Getter, nullptr); //6
- 为什么可以正确超载
&Test::Value
在1中确定,但在2和3中不确定?
- 为什么 1 和 4 能够推导出正确的类型名,而 2、3、5 和 6 却不能?
Edit
我期望能够调用这些方法,并将两个参数中的至少一个设置为实际的指向成员函数的指针,从而使推导成功。就像这样:
Checker::Check(&Test::Value, &Test::Value); // Both getter and setter
Checker::Check(&Test::Value, nullptr); // Only getter
Checker::Check(nullptr, &Test::Value); // Only setter
Edit
@Oliv 的例外答案中的讨论解释了为什么它不能按我的预期工作,为我指明了解决特定问题的正确方向。
正如@Ben Voigt 建议的那样,我最终使用了转发器。就像是:
template <typename T, typename V>
using GetterT = V(T::*)();
template <typename T, typename V>
using SetterT = void(T::*)(V);
template <typename T, typename V>
void Checker::CheckGetterAndSetter(
GetterT<T, V> getter,
SetterT<T, V> setter
)
{
// Do stuff with getter and setter.
}
template <typename T, typename V>
void Checker::CheckGetter(
GetterT<T, V> getter
)
{
SetterT<T, V> null = nullptr;
return CheckGetterAndSetter(getter, null);
}
template <typename T, typename V>
void Checker::CheckSetter(
SetterT<T, V> setter
)
{
GetterT<T, V> null = nullptr;
return CheckGetterAndSetter(null, setter);
}