为模板类中的无效数据类型生成编译时错误?

Mar*_*lon 3 c++ error-handling templates

我正在使用C++创建一个字符串类.我希望该类只接受数据类型char和wchar_t,我希望编译器在编译期间使用#error捕获任何无效的数据类型.我不喜欢使用assert().我怎样才能做到这一点?

GMa*_*ckG 12

您可以使用静态断言.Boost 提供一个.

也许是这样的:

#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;
}
Run Code Online (Sandbox Code Playgroud)

如果你不能使用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;
}
Run Code Online (Sandbox Code Playgroud)

注意,如果在同一名称空间中使用静态断言两次,则会发生名称冲突.您必须使用更复杂的版本,该版本使用宏__COUNTER__来生成唯一的名称.

以上工作在GCC 4.4和Visual Studio 2008中都有效.


R S*_*hko 5

你可以通过专业化来发挥一些技巧.首先声明但不定义模板.

template <class C> class limiter;
Run Code Online (Sandbox Code Playgroud)

然后专门为char和wchar_t定义一些属性.

template <>
class limiter<char>
{
public:
    typedef char limit_type;
}

template <>
class limiter<wchar_t>
{
public:
    typedef wchar_t limit_type;
}
Run Code Online (Sandbox Code Playgroud)

在您的字符串类中,您可以引用:

template <class TYPE>
class mystring
{
   typedef typename limiter<TYPE>::limit_type limit_type;
   ...
}
Run Code Online (Sandbox Code Playgroud)

因为那只对char和wchar_t有效,所以其他类型都不可实例化.