几种类型的C ++模板专业化 [英] C++ template specialization for several types

查看:72
本文介绍了几种类型的C ++模板专业化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,

我正在使用微软的VS2013探索C ++ 11模板。最近我遇到了以下问题:

*我有一个带有虚函数体的模板函数。

*我想创建一个适用于所有合适类型的特化,例如所有整数类型,所有浮点类型或所有字符类型。

让我举个简单的例子。函数Invert应返回位反转参数值,这当然对大多数数据类型没有意义,因此虚拟实现返回0:

Hi all,
I am exploring C++11 templates with Microsoft's VS2013. Recently I came across the following problem:
* I have a template function with a dummy function body.
* I want to create a specialization that works for all suitable types, e.g. all integer types, all floating-point types, or all character types.
Let me give you a simple example. The function Invert should return the bit-inverted parameter value, which of course makes no sense for most data types, so the dummy implementation returns 0:

template<typename T> T Invert(T data)
{ // dummy
    return T();
}



现在我可以开始专门化模板:


Now I can start to specialize the template:

template<> int Invert(int data)
{ // specialized
    return ~data;
}
template<> unsigned Invert(unsigned data)
{ // specialized
    return ~data;
}
//etc.



适用于所有合适的数据类型:char,int,short,long,long long,采用有符号和无符号变体。这会产生成倍增加的代码。所以我认为必须有更好的解决方案,我的猜测是SFINAE就是答案。

我用type_traits风格创建了一个模板类


for all suitable data types: char, int, short, long, long long, in their signed and unsigned variants. That creates multiplied code. So I thought there must be a better solution, and my guess is that SFINAE is the answer.
I created a template class in type_traits style

template<typename T> struct IsSuitableType
{
    static bool const value = std::is_integral<T>::value && !std::is_enum<T>::value && !std::is_same<T, bool>::value;
};



使表达式更短,然后编写通用专业化:


to make expressions shorter, and then wrote "generic" specialization:

template<typename T> std::enable_if_t<IsSuitableType<T>::value, T> Invert(T data)
{ // specialized
    return ~data;
}



但编译测试代码,其中Invert< int>调用给我


but compiling test code where Invert<int> is called gives me

error C2668: 'Invert' : ambiguous call to overloaded function
could be 'int Invert<int>(T)'
or       'T Invert<int>(T)'



(例如,测试代码简单:int i = Invert(3);)

仅当我修改原始模板定义以便我现在具有


(For illustration, the test code is simply: int i = Invert(3);)
This only works if I modify the original template definition so that I now have

template<typename T> std::enable_if_t<!IsSuitableType<T>::value, T> Invert(T data)
{ // dummy
    return T();
}
template<typename T> std::enable_if_t<IsSuitableType<T>::value, T> Invert(T data)
{ // specialized
    return ~data;
}



这使虚拟函数不那么通用,每次添加一些新的特化时我都要修改模板,这不是怎么回事(在我的理解)模板编程应该完成。



如何解决这个问题?


which makes the dummy function less generic, and I would have to modify the template every time I add some new specialization, which is not how (in my understanding) template programming should be done.

How can I solve this problem?

推荐答案

以下链接可能有所帮助:



https:/ /msdn.microsoft.com/en-us/library/ee361639.aspx [ ^ ]

http:// en.cppreference.com/w/cpp/types/enable_if [ ^ ]



顺便说一句,我尝试了你的程序,它完美运行所以我不确定你保留的代码...

The following links might help :

https://msdn.microsoft.com/en-us/library/ee361639.aspx[^]
http://en.cppreference.com/w/cpp/types/enable_if[^]

By the way, I tried your program and it works perfectly so I'm not sure of the code that you have kept...
#include <type_traits>

template<typename T> struct IsSuitableType
{
    static bool const value = 
        std::is_integral<T>::value && 
        !std::is_enum<T>::value && 
        !std::is_same<T>::value;
};

template<typename T> std::enable_if_t<IsSuitableType><T>::value, T> Invert(T data)
{ // specialized
	return ~data;
}



函数中的某个地方:


And somewhere in a function:

int inv = Invert(3);





如果尝试使用不合适的参数( bool const char * ,则会出现编译错误, ...)



And there will be a compilation error if you try with parameters that are not adequate (bool, const char *, ...)


在玩模板的其他方面时,我遇到了解决方案。它缺乏一些优雅,因为它需要一个虚拟参数。



While playing with other aspects of templates, I came across the solution. It lacks some elegance because it requires a dummy parameter.

template<typename U>
U Invert2(U const &data, ...)
{ // default
    return data;
}

template<typename U>
std::enable_if_t<is_suitable_type<U>::value, U> Invert2(U const &data, U const*)
{ // specialized for data types for which bit inversion makes sense
    return ~data;
}

template<typename T>
inline T Invert(T const &data)
{
    return Invert2(data, &data);
}

template<typename T>
void RunTest()
{
    for (auto itr : CTestData<T>::m_Data)
    {
        T data = itr.m_Data;
        T expect = itr.m_Expect;
        T actual = Invert(data);
        ASSERT(expect == actual);
    }
}







我定义了Invert2函数的两个重载,两者都是模板功能。如果U不是合适的类型,则只有第一个过载可用。否则,两个重载都可用,编译器将选择匹配最佳的重载。通过第二个(虚拟)参数,编译器发现第二个重载比第一个重载更好。



反转函数只是一个隐藏传递的包装器第二个参数。



解决方案偏离我原来的问题,因为默认重载返回其参数,而不是U(),因为我的测试包括一个类有一个私有的默认构造函数。



代码本身对解决日常编码问题没有好处。将其视为可以使用C ++ 11模板执行操作的示例。




I defined two overloads of the Invert2 function, both of which are template functions. If U is not a suitable type, then only the first overload is available. Otherwise, both overloads are available, and the compiler will pick the one that matches best. Through the second (dummy) parameter, the compiler finds that the second overload is a better match than the first one.

The Invert function is only a wrapper that hides passing the second parameter.

The solution deviates from my original problem insofar as the "default" overload returns its argument, and not U(), because my test included a class that had a private default constructor.

The code in itself is no good for solving everyday coding problems. View it as an example of what one can do with C++11 templates.


这篇关于几种类型的C ++模板专业化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆