Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 类型的部分模板专门化_C++_Templates_C++11_Specialization - Fatal编程技术网

C++ 类型的部分模板专门化

C++ 类型的部分模板专门化,c++,templates,c++11,specialization,C++,Templates,C++11,Specialization,我有一个类vec_base定义如下: template<typename T, std::size_t Size> class vec_base; 模板 类向量库; 我想专门研究一下,这样 vec_base<float, /* any multiple of 4 */> vec\u基地 及 vec\u基地 可以独立任命特定成员,例如 vec_base<int, 6> vec\u基地 其中包含我已经定义的通用成员 我很难实现这一点,因为如果具体是2

我有一个类
vec_base
定义如下:

template<typename T, std::size_t Size>
class vec_base;
模板
类向量库;
我想专门研究一下,这样

vec_base<float, /* any multiple of 4 */>
vec\u基地

vec\u基地
可以独立任命特定成员,例如

vec_base<int, 6>
vec\u基地
其中包含我已经定义的通用成员

我很难实现这一点,因为如果具体是2或4,我知道我可以执行完全的专门化,那么允许的大小很小(4或2的任意倍数),但事实并非如此:/

我该怎么办?任何帮助都是感激的,我总是喜欢学习新的语言技巧


编辑 好的,到目前为止我有这个:

template<std::size_t Size>
struct is_div_by_4{static const bool value = (Size % 4 == 0);};
// have to define because of template requirements
// about not being dependent on other parameters

template<typename T, std::size_t Size, bool is_special>
class vec_base;

template<typename T, std::size_t Size>
class vec_base<T, Size, false>{
    // generic implementation
};

teplate<std::size_t Size>
class vec_base<float, Size, is_div_by_4<Size>::value>{
    // Special implementation (for sse, it's no secret)
};
模板
结构是_div_by_4{static const bool value=(Size%4==0);};
//由于模板要求,必须进行定义
//关于不依赖于其他参数
模板
类向量库;
模板
类向量库{
//通用实现
};
温板
类向量库{
//特殊实施(对于sse来说,这不是秘密)
};
但我还没有编译它,我知道它不会工作,所以请不要指出这一点;这正是我目前所拥有的,以防你认为我只是把自己的工作推迟到现在。

简单的解决方案 最简单的技巧是使用并类似于您所做的:

template<typename T, std::size_t Size, typename U = void>
class vec_base { /* implement me generically */ };

template<typename T, std::size_t Size>
class vec_base<T, Size, typename std::enable_if<std::is_same<T, float>::value && Size % 4 == 0>::type>
{ /* implement me with 10% more awesome-sauce */ };

template<typename T, std::size_t Size>
class vec_base<T, Size, typename std::enable_if<std::is_same<T, double>::value && Size % 2 == 0>::type>
{ /* implement me with pepper instead */ };
为什么不需要
typename T
std::same
从中您还可以看到,您可以删除专门化的
typename T
,并放弃使用
std::is_same
<代码>T毕竟必须始终是特定类型

template<std::size_t Size>
class vec_base<typename std::enable_if<Size % 4 == 0, float>::type, Size>
{
    friend vec_base operator+(vec_base const& lhs, vec_base const& rhs)
    { /* do some additions */
        return lhs;
    }
};
模板
类向量库
{
友元向量基本运算符+(向量基本常数和左、向量基本常数和右)
{/*做一些补充*/
返回lhs;
}
};
在类之外添加更多运算符相当简单:

// works for all vec_base variants
template<typename T, std::size_t Size>
vec_base<T, Size> operator-(vec_base<T, Size> const& lhs, vec_base<T, Size> const& rhs)
{ /* do some subtractions */
    return lhs;
}

// works only for the specialization float, divisible by 4
template<std::size_t Size>
typename std::enable_if<Size % 4 == 0, vec_base<float, Size>>::type
operator-(vec_base<float, Size> const& lhs, vec_base<float, Size> const& rhs)
{ /* do some salty computations */
    return lhs;
}
//适用于所有vec_基本变体
模板
向量基本运算符-(向量基本常数和左、向量基本常数和右)
{/*做一些减法运算*/
返回lhs;
}
//仅适用于专用浮动,可被4整除
模板
typename std::enable_if::type
操作员-(车辆基本常数和左侧、车辆基本常数和右侧)
{/*做一些粗略的计算*/
返回lhs;
}
这实际上是可行的,因为第二个版本比第一个版本严格限制(使用特殊函数的每个参数组也适用于泛型函数-但泛型函数有一些特殊函数无法使用的参数组)

修正你的尝试 虽然您似乎对您的尝试感到失望,但下面是如何使其适应工作(请注意,此解决方案比上面显示的解决方案复杂得多):

模板
结构向量库;
模板
结构向量库
{static void hello(){::std::cout

template<typename T, std::size_t Size>
class vec_base
{
  public: vec_base() {
      std::cout << "I am generic, my size is " << Size << std::endl;
  }
};

template<std::size_t Size>
class vec_base<typename std::enable_if<Size % 4 == 0, float>::type, Size>
{
  public: vec_base() {
      std::cout << "I am specialized for float, my size is " << Size << std::endl;
  }
};

template<std::size_t Size>
class vec_base<typename std::enable_if<Size % 2 == 0, double>::type, Size>
{
  public: vec_base() {
      std::cout << "I am specialized for double, my size is " << Size << std::endl;
  }
};
模板
类向量库
{
公众:vec_base(){
std::无法将您的特殊性封装在类型特征中
我会选择一个
is_special
类型特征,它为所有不适合SSE解决方案的类型提供
std::false
,反之亦然

#include <cstddef>
#include <iostream>
#include <type_traits>

// test whether a vector of floating points fits into B bits SSE solution
template<typename T, std::size_t N, std::size_t B = 128>
struct is_special
: 
    std::integral_constant<bool, 
        std::is_floating_point<T>::value && 8 * sizeof(T) * N == B
    > 
{};
请注意,泛型模板不需要知道用于专门化的特殊条件的类型。这是开放/封闭原则的体现:您的代码为修改而关闭,但为扩展而打开。对于128位长的双倍体,只需添加一个新的专门化

在实践中测试代码 您可以这样调用此代码:

int main()
{
    vec_base<int, 6>::print();    // vec_base<T, N>
    vec_base<float, 1>::print();  // vec_base<T, N>
    vec_base<float, 4>::print();  // vec_base<float, 4 * K>
    vec_base<double, 1>::print(); // vec_base<T, N>
    vec_base<double, 2>::print(); // vec_base<double, 2 * K>
}
intmain()
{
向量库::print();//向量库
向量库::print();//向量库
向量库::print();//向量库
向量库::print();//向量库
向量库::print();//向量库
}

这将打印上面的注释行。测试您想要的和不想调用SSE代码的情况非常重要。

无需对您的尝试如此不满-它几乎奏效了!几乎奏效了哈哈,我只是不想仔细检查我已经知道我可以做到这一点,我需要专门化它,以便在
t==float&&大小%4==0
是真的,
T==double&&Size%2==0
是真的:LEven在第二次编辑之后,我希望能够编写
vec_base
vec_base
,并使这两个类的方法不同。我已经实现了我的类,就像你在你的帖子中所做的那样:P
enable_if
等等更像它!我没有用过
是相同的
before@CoffeeandCode我只是在把你的代码修改成我认为你想做的事情之后才读到你的评论;)@TemplateRex我添加了一个注释以使它更明显;)非常确定这会导致有关依赖模板的编译错误或一些错误,因为你在它在其中定义的模板,这就是为什么在我的原始问题中,我声明了
is_div_by_4
struct
对我有效。请注意,它的工作方式与另一个答案中的工作方式完全相同,只是没有额外的伪类型参数。如果
大小%2
或更复杂的内容直接传递给e generic
vec_base
。但这里它被传递到
enable_if
。它肯定会工作-但它为什么工作似乎不那么明显;)嗯,我只是猜测,因为我已经尝试将它直接传递到模板中的
bool
,之前您可能违反了14.5.4/9:“部分专门化的非类型参数表达式不得涉及部分专门化的模板参数,除非参数表达式是简单标识符。“也就是说,您有类似于
模板类vec_base
的内容。这是一个禁忌。但是您可以有
模板类vec_base
,因为您在这里传递类型参数。
vec_base<float, 2>::hello(); // hello all
vec_base<float, 4>::hello(); // hello 4 floats
template<typename T, std::size_t Size>
class vec_base
{
  public: vec_base() {
      std::cout << "I am generic, my size is " << Size << std::endl;
  }
};

template<std::size_t Size>
class vec_base<typename std::enable_if<Size % 4 == 0, float>::type, Size>
{
  public: vec_base() {
      std::cout << "I am specialized for float, my size is " << Size << std::endl;
  }
};

template<std::size_t Size>
class vec_base<typename std::enable_if<Size % 2 == 0, double>::type, Size>
{
  public: vec_base() {
      std::cout << "I am specialized for double, my size is " << Size << std::endl;
  }
};
#include <cstddef>
#include <iostream>
#include <type_traits>

// test whether a vector of floating points fits into B bits SSE solution
template<typename T, std::size_t N, std::size_t B = 128>
struct is_special
: 
    std::integral_constant<bool, 
        std::is_floating_point<T>::value && 8 * sizeof(T) * N == B
    > 
{};
template<typename, std::size_t, typename = void>
class vec_base
{
public:
    static void print() { std::cout << "vec_base<T, N>\n"; };    
};

template<std::size_t N>  
class vec_base<float, N, typename std::enable_if<is_special<float, N>::value>::type>
{
public:
    static void print() { std::cout << "vec_base<float, 4 * K>\n"; };    
};

template<std::size_t N> 
class vec_base<double, N, typename std::enable_if<is_special<double, N>::value>::type>
{
public:
    static void print() { std::cout << "vec_base<double, 2 * K>\n"; };    
};
int main()
{
    vec_base<int, 6>::print();    // vec_base<T, N>
    vec_base<float, 1>::print();  // vec_base<T, N>
    vec_base<float, 4>::print();  // vec_base<float, 4 * K>
    vec_base<double, 1>::print(); // vec_base<T, N>
    vec_base<double, 2>::print(); // vec_base<double, 2 * K>
}