我正在使用C ++创建一个字符串类。我希望该类只接受数据类型char和wchar_t,我希望编译器在编译期间使用#error捕获任何无效的数据类型。我不喜欢使用assert()。我怎么能这样做?
答案 0 :(得分:12)
您可以使用静态断言。提升provides one。
可能是这样的:
#include <boost/type_traits.hpp>
#include <boost/static_assert.hpp>
template <typename T>
class my_string
{
public:
// ...
private:
BOOST_STATIC_ASSERT((boost::is_same<T, char>::value ||
boost::is_same<T, wchar_t>::value));
};
int main(void)
{
my_string<char> chstr;
my_string<wchar_t> wstr;
// fails
my_string<int> istr;
}
如果你不能使用Boost,你可以很容易地重新制作static-assert和is_same
:
// static assert failure
template <bool Predicate>
struct STATIC_ASSERT_FAILURE;
template <>
struct STATIC_ASSERT_FAILURE<true> {}; // only true is defined
// static assert test
template <unsigned TestResult>
struct static_assert {};
// static assert macro
#define STATIC_ASSERT(x) typedef static_assert< \
sizeof(STATIC_ASSERT_FAILURE<(x)>)> \
_static_assert_test_
// value is true if T and U are the same type
template <typename T, typename U>
struct is_same
{
static const bool value = false;
};
template <typename T>
struct is_same<T, T>
{
static const bool value = true;
};
template <typename T>
class my_string
{
public:
// ...
private:
STATIC_ASSERT((is_same<T, char>::value || is_same<T, wchar_t>::value));
};
int main(void)
{
my_string<char> chstr;
my_string<wchar_t> wstr;
// fails
my_string<int> istr;
}
注意,如果在同一名称空间中使用静态断言两次,则会发生名称冲突。您必须使用使用诸如__COUNTER__
之类的宏的更复杂版本来生成唯一名称。
上述内容适用于GCC 4.4和Visual Studio 2008。
答案 1 :(得分:5)
你可以通过专业化来玩一些技巧。首先声明,但不要定义模板。
template <class C> class limiter;
然后将它专门用于char和wchar_t并定义一些属性。
template <>
class limiter<char>
{
public:
typedef char limit_type;
}
template <>
class limiter<wchar_t>
{
public:
typedef wchar_t limit_type;
}
在您的字符串类中,您可以参考:
template <class TYPE>
class mystring
{
typedef typename limiter<TYPE>::limit_type limit_type;
...
}
因为它只对char和wchar_t有效,所以其他类型都不可实例化。