任何向量的专门化

Specialization for any vector

本文关键字:专门化 向量 任何      更新时间:2023-10-16

我想在模板类中为T的不同情况定义一个函数。我的问题是定义T是向量(无论它包含什么)的情况。

这是我的第一个尝试:

template<typename T>
class Test{
protected:
    T *val;
public:
    Test(T* v):v(val){};
    static string typeName();
};
template<typename T>
string Test<T>::typeName(){
    return "other";
}
template<>
string Test<int>::typeName(){
    return "int";
}
template<typename T>
string Test<vector<T>>::typeName(){
//error: invalid use of incomplete type ‘class Test<vector<T>>’
    return "vector<" + Test<T>::typeName() + ">";
}
我可以通过定义 来解决这个错误:
template<typename T>
class Test<vector<T>>{
    // ... (the same thing)
}

,但我不想这样做,因为我的类很大,我不想再写同样的函数。如果可能的话,我还希望避免让我的类继承另一个类。

通过搜索这里,我读到关于SFINAE,但我是一个初学者。我试了各种方法,但都没用。这是另一个尝试:

#include <type_traits>
template<typename T,typename E=void>
class Test{
protected:
    T *val;
public:
    Test(T* v);
    static string typeName();
    static void bidon();
};
template<typename T,typename E>
string Test<T,E>::typeName(){
    return "other";
}
template<>
string Test<int>::typeName(){
    return "int";
}
template<typename T> struct IsVector            : public std::false_type{};
template<typename T> struct IsVector<vector<T>> : public std::true_type {};
template<typename T,typename E>
    string Test<T,typename std::enable_if<IsVector<T>::value,E>::type>::typeName(){
    return "vector<" + Test<typename T::value_type>::typeName() + ">";
}

我也有同样的错误。有什么问题吗?我在尝试做不可能的事情吗?

我想你可以用它实现你想要的。结果是一样的,尽管方法有点不同。

template <typename V>
struct typeName {};
// Handle pointers
template <typename V>
struct typeName<V*> {
    static string name;
};
template <typename V>
string typeName<V*>::name = typeName<V>::name + "*";
template <>
struct typeName<string> {
    static string name;
};
string typeName<string>::name = "string";

template <>
struct typeName<int> {
    static string name;
};
string typeName<int>::name = "int";
template <typename V>
struct typeName<vector<V>> {
    static string name;
};
template <typename V>
string typeName<vector<V>>::name = "vector<" + typeName<V>::name + ">";

template <typename V>
struct typeName<set<V>> {
    static string name;
};
template <typename V>
string typeName<set<V>>::name = "set<" + typeName<V>::name + ">";

int main() {
    cout << typeName<vector<string>>::name << endl;   
    cout << typeName<set<string>>::name << endl;   
    cout << typeName<vector<set<string*>*>>::name;   
}

stdout
vector<string>
set<string>
vector<set<string*>*>

由于您的typeName方法同时是staticpublic,您可以使用这样的免费辅助函数:

template< typename T > struct is_vector : std::false_type {};
template< typename... Ts > struct is_vector<vector<Ts...>> : std::true_type {};
// Standard-confirming compilers will accept the above specialization, but
// if your compiler doesn't like the above, you need to manually provide all
// template arguments to detect std::vector properly:
// template< typename T, typename Allocator >
// struct is_vector<vector<T,Allocator>> : std::true_type {};
template<typename T>
typename std::enable_if< !is_vector<T>::value, string >::type testTypeName(){
    return "other";
}
template<typename T>
typename std::enable_if< is_vector<T>::value, string >::type testTypeName(){
    return "vector<" + Test<typename T::value_type>::typeName() + ">";
}
template<>
string Test<int>::typeName(){
    return "int";
}
template<typename T>
string Test<T>::typeName(){
    return testTypeName<T>();
}

我不知道为什么你原来的尝试不工作(就像你一样,我希望它能编译,让我们希望别人能在这一点上有所启示),但作为一种变通方法,你可以做一个单独的模板类,只包含你的静态函数,并在你的主类中使用这个类。类似以下语句:

template<typename T>
struct TypeName {
    static std::string typeName() { return "other"; }
};
template<>
struct TypeName<int> {
    static std::string typeName() { return "int"; }
};
template<typename T>
struct TypeName<std::vector<T>> {
    static std::string typeName() { return "vector<" + TypeName<T>::typeName() + ">"; }
};
template<typename T>
class Test {
public:
    static std::string typeName() { return TypeName<T>::typeName(); }
    // more stuff
};

您可以创建一个单独的模板,其中包含该函数,并让主模板调用辅助模板的函数:

template <typename T>
struct tn_helper {
    static string typeName(){
        return "other";
    }
};
template <typename T>
string Test::typeName(){
    return tn_helper<T>::typeName();;
}
template<>
struct tn_helper<int> {
    static string typeName(){
        return "int";
    }
};
template<typename T>
struct tn_helper<vector<T> > {
    static string typeName(){
        return "vector<" + tn_helper<T>::typeName() + ">";
    }
};
// etc.