【问题标题】:Generating compile time errors for invalid data types in a template class?为模板类中的无效数据类型生成编译时错误?
【发布时间】:2010-12-12 11:41:37
【问题描述】:

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

【问题讨论】:

  • 我很好奇,是什么让其他类型无效?
  • 请注意,#error 用于预处理,您不能在编译时使用它 - 这就是您需要提到的静态断言的原因。

标签: c++ templates error-handling


【解决方案1】:

您可以使用静态断言。提升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 中都有效。

【讨论】:

  • 实际上,我会推荐 BOOST_MPL_ASSERT_MSG,因为编译器发出的消息更具可读性。
【解决方案2】:

您可以通过专业化玩一些技巧。首先声明但不定义模板。

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 有效,因此没有其他类型可实例化。

【讨论】:

  • 谢谢!这是我想要的更多解决方案!我在发布之前尝试使用专业化,但不知道如何生成编译器错误!这是我的解决方案: [code] template struct string_type;模板 struct string_type {};模板 struct string_type {};模板 类字符串:string_type { ... };
  • 老实说,这是静态断言的具体实现。您应该更喜欢使用更通用的解决方案。
  • @GMan,有时一般解决方案比具体解决方案更难理解。但是在一般情况下,您的解决方案当然更好。
猜你喜欢
  • 2011-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多