专门用于生成编译时错误的模板函数

时间:2014-06-16 15:57:21

标签: c++ templates boost static-assert

如果用户尝试使用给定的模板参数调用所述函数,那么如何在编译时专门化模板函数来生成错误?

通过使用以下习惯用语,我能够为模板获取此行为...

template <typename T>
class MyClass< std::vector<T> >;

我想修改的函数的基本签名是......

template <typename T>
T bar(const int arg) const {
  ...
}

如果我使用与以前禁用某些模板类相同的范例 ......

template<>
std::string foo::bar(const int arg) const;

我可以生成链接器错误,我认为这比运行时错误更令人满意,但仍然不是我真正想要的。

由于我无法使用C ++ 11,因此无法使用static_assert,如here所述。相反,我试图像BOOST_STATIC_ASSERT一样使用......

template<>
std::string foo::bar(const int arg) const {
  BOOST_STATIC_ASSERT(false);
  return "";
}

但是,这会产生以下编译时错误,即使我尝试使用我试图禁止的模板参数调用该函数的实例...

error: invalid application of 'sizeof' to incomplete type 'boost::STATIC_ASSERTION_FAILURE<false>'

我找到this post,但它并没有真正提供我觉得适用于我的任何见解。有人可以帮忙吗?

2 个答案:

答案 0 :(得分:5)

使用boost::is_same生成编译时布尔值,然后可以与BOOST_STATIC_ASSERT一起使用来执行检查。

template <typename T>
T bar(const int) 
{
  BOOST_STATIC_ASSERT_MSG((!boost::is_same<T, std::string>::value), 
                          "T cannot be std::string");
  return T();
}

bar<int>(10);
bar<std::string>(10);  // fails static assertion

Live demo

答案 1 :(得分:2)

似乎C ++不允许使用专门的模板成员函数。因此,如果你想使用相同的界面,你应该使用其他技术。我想使用trait_type来实现它。

template <class T>
struct is_string : false_type {};
template <>
struct is_string<string> : true_type {};

template <typename T>
class MyClass {
 private:
  T bar(const int arg, false_type) const {
    return T();
  }

  std::string bar(const int arg, true_type) const {
    return "123";
  }
 public:
  T bar(const int arg) const {
    return bar(arg, is_string<T>());
  }
};

如果您不能使用C ++ 11,则必须自己实现false_type和true_type。或者您可以使用specialize模板类。