0
基於an answer from Nawaz我想使用enable_if來確定模板參數是否是一個容器,如果它是我想顯示類型名稱的自定義消息,而不是來自typeid的名字。我已經通過兩種方式實現了模板專業化。代碼編譯並運行,但在任何情況下都不會調用專用方法。我假設我錯誤地使用了enable_if,這裏的正確應用是什麼? (a)需要的包含文件(b)準備模板代碼(使用SFINAE)(c)假定結構的兩個實現執行任務(d)一些客戶端代碼std :: enable_if在模板參數來確定STL容器
#include <typeinfo>
#include <string>
#include <list>
#include <vector>
#include <iostream>
using namespace std;
template<typename T>
struct has_const_iterator
{
private:
typedef char yes;
typedef struct { char array[2]; } no;
template<typename C> static yes test(typename C::const_iterator*);
template<typename C> static no test(...);
public:
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
typedef T type;
};
template <typename T>
struct has_begin_end
{
template<typename C> static char(&f(typename std::enable_if<
std::is_same<static_cast<typename C::const_iterator(C::*)() const>(&C::begin),
typename C::const_iterator(C::*)() const>::value, void>::type*))[1];
template<typename C> static char(&f(...))[2];
template<typename C> static char(&g(typename std::enable_if<
std::is_same<static_cast<typename C::const_iterator(C::*)() const>(&C::end),
typename C::const_iterator(C::*)() const>::value, void>::type*))[1];
template<typename C> static char(&g(...))[2];
static bool const beg_value = sizeof(f<T>(0)) == 1;
static bool const end_value = sizeof(g<T>(0)) == 1;
};
template<typename T>
struct is_container : std::integral_constant<bool,
has_const_iterator<T>::value &&
has_begin_end<T>::beg_value &&
has_begin_end<T>::end_value>
{ };
struct TypeName {
template <typename T>
static const char* get() {
return typeid(T).name();
}
template <typename T, typename std::enable_if<is_container<T>::value>::type >
static const char* get()
{
typedef typename T::value_type ElementType;
std:string containerType = "";
if (std::is_same<decltype(std::vector<ElementType>), T>::value) {
containerType = "(Vector) ";
}
if (std::is_same<decltype(std::list<ElementType>), T>::value) {
containerType = "(List) ";
}
std::string returnString = "Container " + containerType;
returnString += " of ";
returnString += get<ElementType>();
return returnString.c_str();
}
};
template <typename T> struct GypeName {
static const char* get() {
return typeid(T).name();
}
template <class = typename std::enable_if<is_container<T>::value>::type >
static const char* get()
{
typedef typename T::value_type ElementType;
std:string containerType = "";
if (std::is_same<decltype(std::vector<ElementType>), T>::value) {
containerType = "(Vector) ";
}
if (std::is_same<decltype(std::list<ElementType>), T>::value) {
containerType = "(List) ";
}
std::string returnString = "Container " + containerType;
returnString += " of ";
returnString += GypeName<ElementType>::get();
return returnString.c_str();
}
};
int main(int argc, char** argv) {
cout << is_container<int>::value << endl;
cout << is_container<std::vector<int>>::value << endl;
cout << TypeName::get<int>() << endl;
cout << TypeName::get<std::string>() << endl;
cout << TypeName::get<std::vector<int>>() << endl;
cout << TypeName::get<std::vector<std::vector<int>>>() << endl;
cout << GypeName<int>::get() << endl;
cout << GypeName<std::string>::get() << endl;
cout << GypeName<std::vector<int>>::get() << endl;
cout << GypeName<std::vector<std::vector<int>>>::get() << endl;
return 0;
}
這一切的輸出
0
1
int
class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >
class std::vector<int,class std::allocator<int> >
class std::vector<class std::vector<int,class std::allocator<int> >,class std::allocator<class std::vector<int,class std::allocator<int> > > >
int
class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >
class std::vector<int,class std::allocator<int> >
class std::vector<class std::vector<int,class std::allocator<int> >,class std::allocator<class std::vector<int,class std::allocator<int> > > >
不調用在這兩種情況下的特殊功能。
有在提供的代碼拼寫錯誤/編譯器錯誤,[演示](http://coliru.stacked-crooked.com/a/774f27cddb6363be)一旦修復,(但UB不固定(從臨時返回const char *))。 – Jarod42
該代碼需要boost,並使用C++ 11(visual studio 2015) - 我將刪除引用並提供一些自包含的內容 –
好的,主要問題是enable_if應該位於返回類型而不是模板參數。謝謝Jarod42。 –