2015-12-14 33 views
8

Ben (https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Member_Detector buradan) Bu sınıfın fikrini almak olduğunu düşündüm:Üye Detektörü geri dönüşü neden int olmalı?

template<typename T> 
class DetectX 
{ 
    struct Fallback { int X; }; // add member name "X" 
    struct Derived : T, Fallback { }; 

    template<typename U, U> struct Check; 

    typedef char ArrayOfOne[1]; // typedef for an array of size one. 
    typedef char ArrayOfTwo[2]; // typedef for an array of size two. 

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

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

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

ama ben bir üye double MyTest arıyordu hangi benim durumumda uyarlamak için çalıştı.

struct Fallback { double MyTest; }; 

için

struct Fallback { int X; }; // add member name "X" 

ama dedektör bakılmaksızın bir MyTest üyesi vardı olmadığını tüm sınıfları için "doğru" dönüyordu: Ben bu çizgiyi değiştirdi. Satırı şu şekilde değiştirdim:

ve beklendiği gibi çalıştı.

Geri dönüşün neden gerçekte aradığınız üyenin türü değil, int olması gerektiğini anlatabilir misiniz?

#include <iostream> 
#include <vector> 

// https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Member_Detector 

// Standard point representation 
struct Point3 
{ 
    double X,Y,Z; 
}; 

struct SomethingElse{}; 

template<typename T> 
class DetectX 
{ 
    struct Fallback { int X; }; // add member named "X" 
    struct Derived : T, Fallback { }; 

    template<typename U, U> struct Check; 

    typedef char ArrayOfOne[1]; // typedef for an array of size one. 
    typedef char ArrayOfTwo[2]; // typedef for an array of size two. 

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

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

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

template<typename T> 
class DetectY 
{ 
    struct Fallback { double Y; }; // add member named "Y" 
    struct Derived : T, Fallback { }; 

    template<typename U, U> struct Check; 

    typedef char ArrayOfOne[1]; // typedef for an array of size one. 
    typedef char ArrayOfTwo[2]; // typedef for an array of size two. 

    template<typename U> 
    static ArrayOfOne & func(Check<double Fallback::*, &U::X> *); 

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

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

int main() 
{ 
    std::cout << DetectX<Point3>::value << " " << DetectX<SomethingElse>::value << std::endl; 

    std::cout << DetectY<Point3>::value << " " << DetectY<SomethingElse>::value << std::endl; 

    return 0; 
} 

Benim çıkışı:

cevap

4

It ben çifte olarak int fakat Y olarak X için bakmak İşte burada

bir örnektir int olmak zorunda değildir. Herhangi bir türde olabilir. Sadece her yerde, türü ve ismiyle, doğru başvurmak zorunda:

using Arbitrary = double; 

struct Fallback { Arbitrary X; }; // <== arbitrary type, specific name X 

ve burada:

template<typename U> 
static ArrayOfOne & func(Check<Arbitrary Fallback::*, &U::X> *); 
//        ↑↑↑↑↑↑↑↑↑↑    ↑↑↑ 
//        this type    this name 

fikir bir X yok T takdirde, &U::X ile eşleşecek olan Fallback::X'u bulacaksınız (yalnızca bir tane var - Fallback numaralı telefondan). Ancak, T, X içeriyorsa, arama belirsiz olacaktır. Yani, Fallback::X türünde - int'un en kısa olanı ne olduğu önemli değil. tüm eski tarz üye detektörü daha iyidir yarım düzine başka yollar

template <class T> 
using x_type = decltype(&T::X); 

template <class T> 
using has_x = can_apply<x_type, T>; 

Ayrıca bkz this question:

Not C++ 11'de, bu Yakk en can_apply gibi bir şey ile çok daha kolay .

+0

Şimdi, bunun hangi türden olduğu önemli olmamasını sağladım, ancak yine de 'double' ile çalışmıyor gibi görünüyor (son düzenlememdeki örneğime bakın). –

+0

@DavidDoria Çünkü '& U :: Y' olması gereken' & U :: X' var. – Barry

+0

Wow, demek istediğim, derleyicimin ne istediğimi bilmesi için doğru olanı yazmam gerek !? Gürültü için üzgünüm ... –

İlgili konular