我想在模板类中为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() + ">";
}

我有同样的错误。 它出什么问题了 ? 我想做不可能的事情吗?

===============>>#1 票数:3 已采纳

我认为你可以用这个达到你想要的效果。 即使方法略有不同,结果也是一样的。

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*>*>

===============>>#2 票数:3

由于你的typeName方法既是static又是public ,你可以使用这样的免费助手函数:

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>();
}

===============>>#3 票数:1

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

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.

===============>>#4 票数:1

我不知道为什么你的原始尝试不起作用(就像你希望它编译一样,让我们​​希望其他人可以对此有所了解)但作为一种解决方法,你可以创建一个单独的模板类,它只包含你的静态函数,并在你的主类中使用该类。 有点像:

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
};

  ask by Gilles translate from so

未解决问题?本站智能推荐:

1回复

具有功能并模拟部分模板专业化的SFINAE

我试图制作一个专门提供成员函数Y的函数X,如果不提供成员函数Y,则函数X使用全局非成员函数Y来达到相同的效果。 我目前正在尝试通过以下代码实现 但是在容器同时具有成员函数y和全局非成员函数y的情况下,它也可以在其上工作。 存在编译错误,因为对于第二个版本的函数,模板参数格式错误,
2回复

C ++:手动消除部分专业化的歧义(使用SFINAE)

我正在实现一个通用类,该类对于不同的类型集(不仅对于不同的离散类型)应具有不同的行为。 目的是序列化不同类型的对象以通过自定义协议发送它们(但这是更具教育意义的任务,而不是实用的任务;我是一名对分布式计算感兴趣的学生)。 例如,我需要以不同的方式发送浮点数和整数。 我还想拥有其他POD类型
3回复

我如何专门化我的std :: string模板

我有以下模板化功能 我想这样使用它: 什么是专门针对std::string的功能的好方法,以便我可以编写 我已经尝试了所有已知的方法,但是由于默认类型std::enable_if产生的歧义,它们似乎都失败了。 例如:如果我写: 这将不匹配任何模板重载。 如果我
2回复

如何部分专门化枚举值的类模板?

可以基于枚举值来专门化模板 这是对以下问题的回答的后续问题。 我怎样才能部分专门化所有枚举的类模板? 我已将答案的答案中的代码粘贴到上面链接的问题中。 我的更改出现以下错误。
2回复

如何基于模板化类的基类专门化成员函数

我试图根据模板的类型来专门化模板类的成员函数。 我特别希望基于多态类型的专业化。 我一直在努力的语法。 这是我的尝试,它显然会产生错误: doSomething()声明中的两个或多个数据类型 编译给出 顺便说一句,我确实得到了以下内容进行编译,但是专业化在运行时没有按预期工
1回复

如何使用is_base_of专门化模板而不会与主模板不明确?

使用下面的代码,我得到一个编译器投诉,关于get_code的调用在前两个模板之间是不明确的。 如何设置代码来检测基类,同时还提供专门的表单? 例如,如果以后我有class C : A {} ,它也应该返回ACLASS 。
1回复

为类的特征专业化实现错误消息

当库用户为模板类的模板参数使用错误的类型时,如何实现错误消息? test.cpp(从这里改编) 该代码无法按预期编译。 但是,仅当用户使用错误的类型时,我才能使编译器显示错误。 g++ test.cpp错误消息 问题:它不会显示我想要的错误消息( Sorry, fo
2回复

引用容器的C ++模板专业化

编译器:VC ++ 2015U3 编译错误: 严重性代码说明项目文件行抑制状态错误C2678二进制'==':未找到采用'const std :: reference_wrapper'类型的左操作数的运算符(或没有可接受的转换)ConsoleApplication1 c:\\ p
1回复

SFINAE模板专业化优先级

我期待第三个模板比第二个模板更专业,但我得到了一个模糊的模板实例化 。 有没有办法让第三个模板更专业? 明确检查T是否是第二个模板中的std::array对我不起作用。 我正在编写一个库,希望用户能够定义自己的trait专长。 第二个模板旨在成为没有更具体特征的容器的通用特化。
3回复

C ++模板专业化 - 避免重新定义

我想要一个接受不同类型参数的泛型函数(或方法)。 如果提供的类型具有“one”方法,则该函数应使用它。 如果它有'两个'方法,该函数应该使用它。 这是无效的代码: 是否可以使用SFINAE? 是否可以使用type_traits? 澄清: 如果可以使用SFINAE