如何创建模板属于特定类型的编译时断言?

发布于 2024-12-21 07:23:06 字数 555 浏览 1 评论 0原文

我有一个模板函数,并希望在编译时确保它不会在特定类的子类型或超类型上实例化。

如果违反此规定,如何导致 C++ 编译器错误?

class base {
};
class derived : public base {
};
class lowest : public derived {
};

template <typename T>
bool isCorrect(const T& obj) {
  typedef foo<T> D;
  foo<T> *def = foo<T>::find();
  return (def && def->getAnswer(object));
}

我希望 isCorrect 仅适用于类 衍生,但不适用于 baselowest。请注意,可能存在许多其他最低类和要排除的一系列基类以及可接受的替代派生类。

C++ 中有没有办法限制模板仅适用于我明确指定的派生类?

I have a template function and wish to ensure at compile time that it is not instantiated on a subtype or supertype of a particular class.

How can I cause a C++ compiler error if this is violated?

class base {
};
class derived : public base {
};
class lowest : public derived {
};

template <typename T>
bool isCorrect(const T& obj) {
  typedef foo<T> D;
  foo<T> *def = foo<T>::find();
  return (def && def->getAnswer(object));
}

I want isCorrect to only be available for class derived, but not base or lowest. Note there could be many other lowest classes and a string of base classes to be excluded as well as alternative derived classes that are acceptable.

Is there a way in C++ to limit the template to only apply to the derived classes I explicitly specify?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

俯瞰星空 2024-12-28 07:23:06

类型特征,特别是 is_base_of

#include <type_traits>

template <typename T>
bool isCorrect(const T& obj) {
  static bool const is_base = std::is_base_of<base, T>::value;
  static bool const derives = std::is_base_of<derived, T>::value;
  // specify allowed types here
  static bool const is_derived = std::is_same<T, derived>::value;
  // ---
  static_assert((!is_base && !derives) || is_derived, "wrong argument type");

  typedef foo<T> D;
  foo<T> *def = foo<T>::find();
  return (def && def->getAnswer(object));
}

请注意,这是 C++11 特定的,但您可以使用 Boost.TypeTraits 获得相同的行为。

Type traits, specifically is_base_of.

#include <type_traits>

template <typename T>
bool isCorrect(const T& obj) {
  static bool const is_base = std::is_base_of<base, T>::value;
  static bool const derives = std::is_base_of<derived, T>::value;
  // specify allowed types here
  static bool const is_derived = std::is_same<T, derived>::value;
  // ---
  static_assert((!is_base && !derives) || is_derived, "wrong argument type");

  typedef foo<T> D;
  foo<T> *def = foo<T>::find();
  return (def && def->getAnswer(object));
}

Note that this is C++11 specific, but you can get the same behaviour with Boost.TypeTraits.

不寐倦长更 2024-12-28 07:23:06

这是我所知道的一种技术。

首先,创建另一个模板类policy_enforcer。声明此类而不定义它,并为派生提供它的特化也已定义

template<typename T> struct policy_enforcer;
template<> struct policy_enforcer<derived> { };

然后,在您希望的函数中锁定,包括表达式 sizeof(policy_enforcer)。由于不完整类型上的 sizeof 是一个编译错误,这将阻止代码编译。

使用实时代码更新: 使用 base, < a href="http://www.ideone.com/uOdLk" rel="nofollow">使用派生使用最低

Here's one technique that I know of.

First, make another template class policy_enforcer. Declare this class without defining it, and also provide a specialization of it for derived that is also defined:

template<typename T> struct policy_enforcer;
template<> struct policy_enforcer<derived> { };

Then, within the function you wish to lock down, include the expression sizeof(policy_enforcer<T>). Since sizeof on incomplete types is a compilation error, this will prevent the code from compiling.

Updated with live code: using base, using derived, using lowest.

红ご颜醉 2024-12-28 07:23:06

您可以使用模板专门化。

您只能为您希望使用的类型实现 isCorrect

对于其他类型,您可以实现虚拟方法,例如返回 false,或者根本不实现 isCorrect,在这种情况下,它将无法针对其他类型进行编译。

#include <iostream>

using namespace std;

class base {
};
class derived : public base {
};
class lowest : public derived {
};

// using this it will fail if you try to pass anything
// else than `derived`
//  template <typename T>
//     bool isCorrect(const T& obj);

template <typename T>
bool isCorrect(const T& obj) {
    cout << __PRETTY_FUNCTION__ << endl;
    return false;
}

template <>
bool isCorrect<derived>(const derived& obj) {
    cout << __PRETTY_FUNCTION__ << endl;
    return true;
//  typedef foo<derived> D;
//  foo<derived> *def = foo<derived>::find();
//  return (def && def->getAnswer(object));
}

测试:

int main()
{
    base b;
    derived d;
    lowest l;

    cout << isCorrect(b) << endl;
    cout << isCorrect(d) << endl;
    cout << isCorrect(l) << endl;
}

输出:

bool isCorrect(const T&) [with T = base]
0
bool isCorrect(const T&) [with T = derived]
1
bool isCorrect(const T&) [with T = lowest]
0

You can use template specialization.

You can implement only the isCorrect only for types that you want to be able to work with.

For the other types you can implement dummy method, returning false for example, or not implement isCorrect at all, in which case it will not compile for other types.

#include <iostream>

using namespace std;

class base {
};
class derived : public base {
};
class lowest : public derived {
};

// using this it will fail if you try to pass anything
// else than `derived`
//  template <typename T>
//     bool isCorrect(const T& obj);

template <typename T>
bool isCorrect(const T& obj) {
    cout << __PRETTY_FUNCTION__ << endl;
    return false;
}

template <>
bool isCorrect<derived>(const derived& obj) {
    cout << __PRETTY_FUNCTION__ << endl;
    return true;
//  typedef foo<derived> D;
//  foo<derived> *def = foo<derived>::find();
//  return (def && def->getAnswer(object));
}

Test:

int main()
{
    base b;
    derived d;
    lowest l;

    cout << isCorrect(b) << endl;
    cout << isCorrect(d) << endl;
    cout << isCorrect(l) << endl;
}

Output:

bool isCorrect(const T&) [with T = base]
0
bool isCorrect(const T&) [with T = derived]
1
bool isCorrect(const T&) [with T = lowest]
0
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文