template<typename T, T> 是什么意思?

Edu*_*yan 7 c++ templates member-pointers sfinae

我正在阅读这个史前元程序示例来检测一个类是否支持成员查找。(或任何其他成员)。

template<typename T>
class DetectFind
{
    struct Fallback { int find; }; 
    struct Derived : T, Fallback { };

    template<typename U, U> struct Check;

    typedef char Yes[1];  
    typedef char No[2]; 

    template<typename U>
    static No& func(Check<int Fallback::*, &U::find>*);

    template<typename U>
    static Yes& func(...);

public:
    typedef DetectFind type;
    enum { value = sizeof(func<Derived>(0)) == sizeof(Yes) };
};

int main()
{
    std::cout << DetectFind<std::vector<int> >::value << std::endl;
    std::cout<< DetectFind<std::set<int> >::value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

直觉上我确实理解这背后的目的,但如果有人让我在 10 天后从头开始写同样的东西,我可能会失败。
原因是我不完全理解这里使用的句法和语言延伸。
有人可以解释以下语法的含义吗?

  1. Check<int Fallback::*, &U::find>* (我知道它试图在这里从 SFIANE 中受益,但是这是如何检测 find 的存在的,我相信这也与第二个问题有关)
  2. template<typename U, U> struct Check;

程序输出 0 1 如预测;

Who*_*aig 6

template<typename U, U>意味着有两个模板参数:一个任意类型 U 和一个未命名的非类型模板参数(例如一个值参数),其类型为 U。例如,一个int场景是ClassName<int,42>.

在您的示例中,类型U是指向int成员的指针,值是int成员的地址。


fra*_*sco 2

首先,让我们考虑一下 struct Derived。因为它派生自Fallback它,所以肯定包含一个 int 字段find,并且可能包含一个成员函数find,您要检查其是否存在。

如上面的答案所述,在 的声明中struct Check,第一个模板参数是类型,第二个是非类型参数,其类型由第一个参数给出。

鉴于此,让我们检查 的两个重载func。第一个重载采用一个指向Check结构的指针,该结构的第一个模板参数的类型等于Fallback( int Fallback::*) 的 int 成员指针。然后,第二个模板参数被解释为值为 的指向 int 成员的指针&U::find。给定U = Derived,如果T包含find成员函数,则 的第二个参数Check是不明确的,因为它也可以引用int find由 继承的Fallback。通过 SFINAE,该重载func将被丢弃。

第二个func重载总是被明确定义的。但如果第一个重载没有被丢弃,第二个重载的专业性较低,因此编译器将选择第一个重载。

总之:如果Uintemplate <typename U> func包含成员函数find,编译器会选择 的第二个重载func。如果成员函数find不存在,编译器将选择第一个重载。

最后, 的值DetectFind由所选 的返回类型的大小决定func,根据重载,该类型是大小为 1 或 2 的 char 数组。从那里,您可以了解func选择的重载,并根据上面的讨论,是否T有成员函数find