简体   繁体   English

从指针到成员的模板推导,其中至少一个成员指针是已知的

[英]Template deduction from pointer-to-members, where at least one pointer-to-member is known

Consider a struct with static method templates that accept pointer-to-member functions.考虑一个带有静态方法模板的结构,它接受指向成员函数的指针。 Note that when one of the arguments to the methods is an actual pointer-to-member function, both template parameters can be deduced, regardless if the other argument is a nullptr or not.请注意,当方法的参数之一是实际的指向成员函数的指针时,可以推导出两个模板参数,无论另一个参数是否为nullptr

See questions below the following code:请参阅以下代码下方的问题:

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
  • Why can the correct overload of &Test::Value be determined in 1, but not in 2 and 3?为什么可以在 1 中确定&Test::Value的正确重载,而不能在 2 和 3 中确定?
  • Why are 1 and 4 able to deduce the correct typenames, but 2, 3, 5 and 6 not?为什么 1 和 4 能够推断出正确的类型名,而 2、3、5 和 6 则不能?

Edit编辑

I was expecting to be able to call the methods with at least one of the two arguments set to an actual pointer-to-member function, causing deduction to succeed.我希望能够调用这些方法,并将两个参数中的至少一个设置为实际的指向成员函数的指针,从而导致推导成功。 Like so:像这样:

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编辑

The discussion in the excepted answer by @Oliv explaining why it doesn't work as I expected, pointed me in the right direction for solving my specific problem. @Oliv 在例外答案中的讨论解释了为什么它没有按我预期的那样工作,为我指明了解决我的具体问题的正确方向。

I ended up using forwarders, as @Ben Voigt suggested.正如@Ben Voigt 建议的那样,我最终使用了转发器。 Something like:就像是:

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);
}

TL;DR It succeeds because default arguments are not used for template argument deduction . TL;DR 它成功了,因为默认参数不用于模板参数推导 In the others cases (2,3,5,6) it fails because nullptr_t has not the form of a T(U::*)(V) (not even a T* ).在其他情况下 (2,3,5,6) 失败,因为nullptr_t没有T(U::*)(V) (甚至不是T* )。

Let's take a simpler example:我们举一个更简单的例子:

template<class T>
void f(T,T*=nullptr);
int main(){
  f(10,nullptr);// (1) error
  f(10);// (2) OK
  }

For (1) the compiler considers it should be able to deduce T from both the first argument and second arguments because a parameter of the form T or T* are deductibles .对于 (1) 编译器认为它应该能够从第一个参数和第二个参数中推导出T ,因为TT*形式的参数是deductibles Since nullptr_t as not the shape of a T* the compilation fails.由于nullptr_t不是T*的形状,因此编译失败。

For (2) the compiler only performs template argument deduction for the first parameter of the function because default arguments does not play in template argument deduction .对于 (2) 编译器只对函数的第一个参数执行模板参数推导,因为默认参数不参与模板参数推导 So it deduces without ambiguity that T is int .所以它可以毫不含糊地推导出Tint Then when the function will be called, nullptr will be converted to a int* .然后当函数被调用时, nullptr将被转换int*

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM