2013-07-16 82 views
7

我想了解static_assert的用处,并且我想知道它是否可以帮助我强制执行设计,如果是这样,如何实现。通过static_assert实施模板类型

我有一个通用模板类,它隐藏了自己的实现内部另一个模板类,这是部分专用的基于模板类型的大小。下面是该外观设计的简要概述:

template <class T, size_t S = sizeof(T)> 
struct Helper; 

template <class T> 
struct Helper<T, sizeof(long)> 
{ 
    static T bar(); 
}; 

// ... other specializations ... 

template <class T> 
class Foo 
{ 
public: 

    T bar() 
    { 
     return Helper<T>::bar(); 
    } 
}; 

如果T大小由助手的专业化支持,才支持。例如,Foo<long>Foo<unsigned long>都支持。但是,假设用户试图构建一个Foo<bool>。通常,这会产生错误,因为助手对于bool没有定义,这是预期的行为。

在这个设计中有没有什么办法可以使用static_assert为这个接口的用户提供更多有用的错误?

此外,我想也限制用户使用特定类型,即使尺寸可能是正确的。例如,不应允许使用Foo<float>。现在,我知道强制执行此操作的唯一方法是通过文档中的大胆评论。 :)

+0

更一般地想一想,它只是支持整数类型?没有'char','bool','float'等等? – Rapptz

+0

搜索模板类型约束或“概念”。在最后一刻从C++ 11中删除了这样做的工具。尽管如此,自动获取类似结果的方法却较少。 – luke

+0

@Rapptz,'char','int'和'long'以及它们的'unsigned'版本应该被支持。如果sizeof(int)== sizeof(long)== sizeof(unsigned long)',那么代码对于int,long和unsigned long是相同的。 – Zeenobit

回答

1

我在这里通过合并的答案和注释想通了这个问题更好的解决方案。

我可以定义一个静态类型检查就像这样:

template <class A, class B> 
struct CheckTypes 
{ 
    static const bool value = false; 
}; 

template <class A> 
struct CheckTypes<A, A> 
{ 
    static const bool value = true; 
}; 

不知道这样的结构在标准库中已经存在。不管怎么说,然后在美孚,我可以通过检查类型和大小:

static_assert((sizeof(T) == sizeof(long) || sizeof(T) == sizeof(int)) && !CheckTypes<T, float>::value, "Error!"); 
+1

它呢,std :: is_same –

+1

使用sizeof是不安全的。它只是大小。 long和int可能具有相同的大小,而只包含int的随机结构也会具有相同的大小。 –

13

如果它只能为模板类的专业化工作,然后有默认的模板类提高静态断言:

template <class T, size_t S = sizeof(T)> 
struct Helper 
{ 
    static_assert(sizeof(T) == -1,"You have to have a sepecialization for Helper!"); 
} 

如果没有默认的模板类才会被选择一个更好的专业化,因此断言将会上升。

您可以使用相同的技术来禁止类型,但您需要另一个将用于静态断言检查的模板参数。

template <class T, class G = T, size_t S = sizeof(T)> 
struct Helper 
{ 
    static_assert(sizeof(G) == -1,"You have to have a sepecialization for Helper!"); 
} 

template <class G> 
struct Helper<float,G> 
{ 
    static_assert(sizeof(G) == -1,"You can't use float !"); 
} 

template <> 
struct Helper<int> 
{ 
//This is a good specialization 
}; 

然后,您可以用这些变量试试:

Helper<bool> a; //"You have to have a sepecialization for Helper!" 
Helper<float> b; //"You can't use float !" 
Helper<int> c; //compiles OK 
+1

我相信你想'static_assert(false,...)',所以它总是跳闸。如果第一个参数为false,'static_assert'将输出错误。 –

+0

+1为实用的答案 – sehe

+9

这不会按原样工作 - 您需要使断言相关(如'static_assert(sizeof(T)== 0,...);'),否则它会在声明点,而不是实例化。 – Angew

3

http://en.cppreference.com/w/cpp/header/type_traits

std::is_base_ofstd::is_convertible可以与你的第一个问题和第二个帮助,

static_assert(!std::is_same<float,T>(),"type can't be float");

希望这可以帮助别人谁发现这个问题,假设OP可能在4年内找到答案sin它被问:) :)