2012-12-19 10 views
6

Tôi dường như không thể tìm ra giải pháp tốt để sử dụng SFINAE với các lớp mẫu có định dạng variadic.SFINAE với các lớp mẫu variadic?

Hãy nói rằng tôi có một mẫu đối tượng variadic mà không thích tham khảo:

template<typename... Args> 
class NoRef 
{ 
    //if any of Args... is a reference, this class will break 
    //for example: 
    std::tuple<std::unique_ptr<Args>...> uptrs; 
}; 

Và một lớp mà thuận tiện kiểm tra nếu một gói luận chứa tài liệu tham khảo:

template<typename T, typename... Other> 
struct RefCheck 
{ 
    static const bool value = std::is_reference<T>::value || RefCheck<Other...>::value; 
}; 
template<typename T> 
struct RefCheck<T> 
{ 
    static const bool value = std::is_reference<T>::value; 
}; 

Làm thế nào để sử dụng điều này để chuyên NoRef cho trường hợp tài liệu tham khảo có mặt trong gói arg?

Trả lời

9

này không sử dụng SFINAE, nhưng về cơ bản những gì bạn có ý định:

template<bool Ref, typename... Args> 
class NoRef_; 

template<typename... Args> 
class NoRef_<false, Args...> 
{ 
    std::tuple<std::unique_ptr<Args>...> uptrs; 
}; 
template<typename... Args> 
class NoRef_<true, Args...> 
{ 
    // contains reference 
}; 

template<typename... Args> 
using NoRef = NoRef_<RefCheck<Args...>::value, Args...>; 

// alternative from Nawaz 

template<typename... Args> struct NoRef : NoRef_<RefCheck<Args...>::value, Args...> {} 
+0

+1. Nhưng tôi nghĩ rằng 'template struct NoRef: NoRef_ :: giá trị, Args ...> {};' sẽ tốt hơn. Bây giờ 'NoRef' là một mẫu lớp khác mà không có tham số mẫu không kiểu (tức là giá trị boolean). – Nawaz

+0

Tôi thích giải pháp này, mặc dù tôi không thể tạo mẫu bí danh trong MSVC. Nhưng Nawaz cũng cung cấp một giải pháp cho điều đó. –

6

Tôi e rằng điều này không thể thực hiện được vì các gói mẫu khó sử dụng. Tuy nhiên, bạn có thể gói gói.

// Used to transport a full pack in a single template argument 
template <typename... Args> struct Pack {}; 

Chúng thích nghi với việc kiểm tra tài liệu tham khảo:

template <typename T, typename... Other> 
struct RefCheck 
{ 
    static const bool value = std::is_reference<T>::value 
          || RefCheck<Other...>::value; 
}; 

template <typename T> 
struct RefCheck<T> 
{ 
    static const bool value = std::is_reference<T>::value; 
}; 

template <typename... Args> 
struct RefCheck<Pack<Args...>>: RefCheck<Args...> {}; 

Và bây giờ chúng ta có thể sử dụng Pack:

template <typename P, bool = RefCheck<P>::value> class NoRef; 

template <typename... Args> 
class NoRef<Pack<Args...>, false> { 
    // no reference in Args... here 
};