2015-09-21 13 views
5

Lưu ý: ví dụ được cung cấp trong câu hỏi này không phải là mã sản xuất và không có ý nghĩa gì cả. Nó chỉ ở đó để minh họa cho vấn đề của tôi.Loại thông số chức năng sử dụng decltype

tôi đã được thử nghiệm các khả năng của decltype, đặc biệt là nếu nó được sử dụng để suy ra các loại tham số chức năng, và chạy vào một vấn đề:

Giả sử có hai lớp có cấu trúc như thế này:

struct ClassInt 
{ 
    // Note: no default ctor 
    ClassInt(int value) 
     : m_Value(value) 
    {} 

    int m_Value; 
}; 

struct ClassDouble 
{ 
    // Note: no default ctor 
    ClassDouble(double value) 
     : m_Value(value) 
    {} 

    double m_Value; 
}; 

Bây giờ, tôi đã viết một hàm (bằng cách nào đó) lấy một thể hiện của tham số kiểu (mà phải là một trong các giá trị trên) bằng chuỗi và gán giá trị đã cho cho thành viên m_Value:

template< typename Ty > 
Ty* get_fake_ptr() { return nullptr; } 


// Retrieve pointer to Ty object by name and assign its value member. 
// The problem is that we don't actually have an instance of Ty at the point 
// where we want to define the type of the parameter "value". 
template< typename Ty > 
void assign(std::string name, decltype(get_fake_ptr<Ty>()->m_Value) value) 
{ 
    // Somehow get pointer to a Ty object by name 
    Ty* obj = ????; 

    // Assign 
    obj->m_Value = value; 
} 

Hiện tại, loại thông số value phụ thuộc vào thông số loại, vì các lớp được sử dụng khác nhau theo loại thành viên m_Value. Như bạn thấy, tôi đã giải quyết nó bằng cách sử dụng decltype. Bây giờ, bình thường, bạn sẽ sử dụng decltype trên một tham số, như thế này:

template<typename Ty> 
void assign(Ty& obj, decltype(obj.m_Value) value); 

Nhưng điều đó rõ ràng là không thể thực hiện ở đây từ các ví dụ thực tế được lấy trong các cơ quan chức năng và vì thế không có sẵn tại điểm mà đối số chức năng được khai báo.

Tôi đã tấn công nó với nhau bằng cách sử dụng hàm mẫu get_fake_ptr, chỉ trả về nullptr loại kết hợp để tôi có một "phiên bản giả" mà trình biên dịch có thể sử dụng để xác định loại thành viên. Và nó hoạt động:

working

Bây giờ, như tôi đã nói, điều này dường như thực sự hacky với tôi. Vì vậy:

Có cách nào tốt hơn để giải quyết vấn đề này không?

Cảm ơn bạn!

+2

Bạn có thể sử dụng 'decltype (std :: declval () .m_Value)' để suy ra kiểu thành viên m_Value của T thay vì sử dụng hàm 'get_fake_ptr()'. Họ hoàn thành mục tiêu tương tự cuối cùng, tôi cho là vậy. –

+1

Nhân tiện, hàm 'get_fake_ptr()' của bạn không cần phải được xác định. Bạn có thể đơn giản để nó như là 'template T * get_fake_ptr();' và bạn vẫn có thể sử dụng nó bên trong 'decltype'. –

+1

Có gì sai với 'decltype (Ty :: m_value)'? – Casey

Trả lời

3

Bạn có thể sử dụng decltype(std::declval<T>().m_Value) để suy ra loại m_Value viên T 's thay vì sử dụng chức năng get_fake_ptr() của bạn. Họ hoàn thành mục tiêu tương tự cuối cùng.

Nhân tiện, chức năng get_fake_ptr() của bạn không cần phải được xác định. Bạn có thể để nó đơn giản là template <typename T> T* get_fake_ptr(); và bạn vẫn có thể sử dụng nó bên trong decltype.

3

Tôi thấy không có gì sai với cách tiếp cận này.

Khi nói đến lập trình meta mẫu, các loại "hack" này tương đương với khóa học.

Tôi có thể đề xuất, tuy nhiên, một mẫu thiết kế hơi khác. Một cái gì đó như thế này:

struct ClassInt 
{ 
    // Note: no default ctor 
    ClassInt(int value) 
     : m_Value(value) 
    {} 

    typedef int m_value_t; 

    m_value_t m_Value; 
}; 

struct ClassDouble 
{ 
    // Note: no default ctor 
    ClassDouble(double value) 
     : m_Value(value) 
    {} 

    typedef double m_value_t; 

    m_value_t m_Value; 
}; 

// ... 
template< typename Ty > 
void assign(std::string name, typename Ty::value_t value) 
{ 
    // Somehow get pointer to a Ty object by name 
    Ty* obj = ????; 

    // Assign 
    obj->m_Value = value; 
} 
2

Một cách khác là thêm một thông số mẫu khác và chỉ cho phép gán xử lý các loại so khớp và chuyển đổi. Mọi loại giá trị không thể chuyển đổi sẽ tạo ra lỗi biên dịch.

template<typename Ty, typename VALUE_TYPE> 
void assign(std::string name, VALUE_TYPE value) { 
    Ty* obj = ??? 
    obj->m_Value = value; 
} 
Các vấn đề liên quan