简体   繁体   中英

Specialize a Template Function to Generate a Compile-Time Error

How does one specialize a template function to generate an error at compile-time if a user attempts to call said function with a given template parameter?

I was able to get this behavior for a template class by using the following idiom...

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

The basic signature of the function which I am trying to modify is...

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

If I use the same paradigm that I used to disallow certain template classes ...

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

I can generate a linker error, which I suppose is more desirable than a runtime error, but still not really what I'm looking for.

Since I am not able to use C++11, I cannot use static_assert , as described here . Instead, I am trying to use BOOST_STATIC_ASSERT like so...

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

However, this generates the following compile-time error, even when I am not trying to call an instance of the function with the template parameter I am attempting to disallow...

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

I found this post , but it doesn't really offer any insight that I feel applies to me. Can anyone help?

Use boost::is_same to generate a compile-time boolean value that can then be used with BOOST_STATIC_ASSERT to perform the check.

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

It seems C++ don't allow specialize template member function. So if you want to use same interface, you should use other technology. I'd like to use trait_type to implement this.

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>());
  }
};

If you can not use C++11, you must implement false_type and true_type yourself. Or you can use specialize template class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM