有没有办法在C ++中隐式匹配嵌套模板类型?

时间:2016-08-26 09:42:39

标签: c++ templates

我有以下MWE:

#include <iostream>
#include <memory>

class A {
public:
    int n = 42;
    typedef std::shared_ptr<A> Ptr;
};

template<typename T>
void foo(typename T::Ptr arg) {
    std::cout << arg->n << std::endl;
}

template<typename T>
void bar(T arg) {
    std::cout << arg.n << std::endl;
}

int main() {
    A::Ptr a = A::Ptr(new A());
    foo<A>(a); // Can I avoid giving <A> here explicitly.
    // foo(a); // does not compile
    bar(*a); // after all this does work
    return 0;
}

对我来说,看起来也应该可以拨打foo(a)而不是foo<A>(a)。为什么这不可能,我可以以某种方式更改foo的定义以使其成为可能吗?

我意识到我可以跳过签名中的::Ptr,但我仍然想要在没有指针的情况下访问A类型。

2 个答案:

答案 0 :(得分:8)

这是不可能的,因为是不可导出的上下文。

a的类型只是std::shared_ptr<A>,这意味着如果 foo(a)有效,那么以下应该工作:

std::shared_ptr<A> x(new A());
foo(x);

如果是这样,那么T应该推断出什么?为什么?您可能会想“ T应推断为A,因为A的嵌套类型Ptrstd::shared_ptr<A> <相同/ EM>”。那么,如果有另一个类被定义为:

struct B
{
    typedef std::shared_ptr<A> Ptr;
};

T应该推断出什么? AB?或其他什么?

以下是使用其他示例讨论不可导入的上下文的另一个主题:

希望有所帮助。

答案 1 :(得分:4)

Nawaz的回答解释了为什么代码不起作用,我将专注于这个问题:

  

但我仍然想要在没有指针的情况下访问A类型。

std::shared_ptr的成员类型为element_type,您可以像typename T::element_type一样使用它。如果你希望代码也适用于原始指针,你可以提供一个特征类模板:

template <typename T>
struct trait_element_type {
    using element_type = std::remove_pointer_t<T>;
};

template <typename T>
struct trait_element_type<std::shared_ptr<T>> {
    using element_type = T;
};

然后将其用作:

template<typename T>
void foo(T arg) {

    std::cout << arg->n << std::endl;

    typename trait_element_type<T>::element_type x; // retrieve the element type
    std::cout << x.n << std::endl;
}

LIVE