C++ 如果使用typedef,则无法推断模板参数

C++ 如果使用typedef,则无法推断模板参数,c++,C++,我有一个“无法推断T的模板参数”错误的问题 这是我的班级: class PropertyAccess { public: template <typename TClass, typename TType> struct SetterPointer { typedef void (TClass::*Type)(const TType&); }; template <typename TClass, typename TType>

我有一个“无法推断T的模板参数”错误的问题

这是我的班级:

class PropertyAccess
{
public:
    template <typename TClass, typename TType>
    struct SetterPointer { typedef void (TClass::*Type)(const TType&); };

    template <typename TClass, typename TType>
    struct GetterPointer { typedef TType(TClass::*Type)(); };

    template <typename TClass, typename TType>
    void Assign(
        TClass* object,
        typename SetterPointer<TClass, TType>::Type setter,
        typename GetterPointer<TClass, TType>::Type getter)
    {
        ...
    }
}
类属性访问
{
公众:
模板
结构SetterPointer{typedef void(TClass::*Type)(const TType&);};
模板
结构GetterPointer{typedef TType(TClass::*Type)(;};
模板
无效转让(
TClass*对象,
typename setterInter::类型setter,
类型名称GetterPointer::类型getter)
{
...
}
}
下面是我如何使用它:

class Test
{
public:
    int a;

    void Set(const int& v) { a = v; }
    int Get() { return a; }
};

void main
{
    Test test;
    PropertyAccess property;
    property.Assign(&test, &Test::Set, &Test::Get);  <---here is compile error
}
类测试
{
公众:
INTA;
空集(常数int&v){a=v;}
int Get(){返回一个;}
};
真空总管
{
试验;
财产取得财产;

property.Assign(&test,&test::Set,&test::Get);C++无法从其嵌套类型推断封闭类型。这是一个非推断上下文的示例

一个最简单的例子是

struct S { typedef int T; };

template <typename C> void foo(typename C::T i) {}

int main()  {
   int x = 0;
   foo(x); // ERROR: non-deduced context
}

C++无法从嵌套类型推断封闭类型。这是未推断上下文的一个示例

一个最简单的例子是

struct S { typedef int T; };

template <typename C> void foo(typename C::T i) {}

int main()  {
   int x = 0;
   foo(x); // ERROR: non-deduced context
}

非常全面的回答,谢谢。有一件事我仍然不明白:为什么它对setter正确工作?请注意,我必须更改only getter定义以使代码正确编译。@majakthecoder:它实际上不“工作”同样,编译器要做的是推导
Assign
的两个模板参数:parameter
TClass
和parameter
TType
。编译器检查
Assign
的第一个参数(
object
)这立即允许它推断出
TClass==Test
。因此,
TClass
参数现在得到处理。编译器继续执行
Assign
-
setter
-的第二个参数,发现它没有用,因为上下文是不可推断的。编译器只是跳过它。然后编译器继续执行t第三个参数
TType(TClass::*getter)(
,并从中推断出
TClass==Test
(与前面的推断一致)并且
TType==int
。现在查看所有参数。所有模板参数的推导和推导都是一致的。因此,代码可以编译。因此,非推导上下文不是错误。推导算法只会忽略非推导上下文中的参数。如果您的所有模板参数都将由其他人推导ans(通过其他函数参数),则您仍然可以。但是,如果您最终得到的模板参数无法从任何函数参数中推导出来,代码将无法编译。@majakthecoder:您可以使用C++11的“模板类型定义”(又名别名模板)功能。
使用SetterPointer=void(TClass::*)的模板(const TType&);
非常全面的答案,谢谢。有一件事我仍然不明白:为什么它对setter正确工作?请注意,我必须只更改getter定义才能使代码正确编译。@majakthecode:它实际上不“工作”同样,编译器要做的是推导
Assign
的两个模板参数:parameter
TClass
和parameter
TType
。编译器检查
Assign
的第一个参数(
object
)这立即允许它推断出
TClass==Test
。因此,
TClass
参数现在得到处理。编译器继续执行
Assign
-
setter
-的第二个参数,发现它没有用,因为上下文是不可推断的。编译器只是跳过它。然后编译器继续执行t第三个参数
TType(TClass::*getter)(
,并从中推断出
TClass==Test
(与前面的推断一致)并且
TType==int
。现在查看所有参数。所有模板参数的推导和推导都是一致的。因此,代码可以编译。因此,非推导上下文不是错误。推导算法只会忽略非推导上下文中的参数。如果您的所有模板参数都将由其他人推导ans(通过其他函数参数),则您仍然可以。但是,如果您最终得到的模板参数无法从任何函数参数中推导出来,代码将无法编译。@majakthecoder:您可以使用C++11的“模板类型定义”(又名别名模板)功能。
使用SetterPointer=void(TClass::*)的模板(const TType&);
一个有趣的问题。问题的一部分是
SetterPointer
GetterPointer
试图成为元函数,但您并不是用两个参数“调用”它们。如果我添加这个重载,调用元函数,它会起作用:template void Assign(TClass*object,T1 setter,T2 getter){Assign*getter())>(object,setter,getter);}就是这么说的“如果我想用一个类和两个类型分配
,请查找getter的结果类型并使用它。有趣的问题。问题的一部分是,
SetterPointer
GetterPointer
试图成为元函数,但您不是在“调用”如果我添加这个重载,调用元函数,它会工作:模板void Assign(TClass*object,T1 setter,T2 getter){Assign*getter())>(object,setter,getter);}也就是说“如果我想用一个类和两个类型分配,请查找getter的结果类型并使用它。
struct S { typedef int T; };

template <typename C> void foo(typename C::T i) {}

int main()  {
   int x = 0;
   foo(x); // ERROR: non-deduced context
}
template <typename X> struct S { typedef X T; };

template <typename X> void foo(typename S<X>::T i) {}

int main()  {
   int x = 0;
   foo(x); // ERROR: non-deduced context
}
class PropertyAccess
{
public:
    template <typename TClass, typename TType>
    using SetterPointer = void (TClass::*)(const TType&);

    template <typename TClass, typename TType>
    using GetterPointer = TType(TClass::*)();

    template <typename TClass, typename TType>
    void Assign(
        TClass* object,
        SetterPointer<TClass, TType> setter,
        GetterPointer<TClass, TType> getter)
    {
       ... 
    }
};