C++力模板参数

发布于 2024-08-16 02:16:45 字数 348 浏览 8 评论 0 原文

我希望这段代码是可能的。

template<typename K, typename T, typename Comparer>
class AVLTree
{
   ...
   void foo() {
       ...
       int res = Comparer::compare(key1, key2);
       ...
   }
   ...
};

具体来说,我想强制 Comparer 类具有 static int Compare(K key1, K key2) 函数。我正在考虑使用推导,但找不到任何可以使用模板的想法。

谢谢。

I want this code to be possible.

template<typename K, typename T, typename Comparer>
class AVLTree
{
   ...
   void foo() {
       ...
       int res = Comparer::compare(key1, key2);
       ...
   }
   ...
};

Specifically, I want to force Comparer class to have a static int compare(K key1, K key2) function. I was thinking about using derivation, but could not find any ideas that can work with templates.

Thank you.

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

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

发布评论

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

评论(8

零度° 2024-08-23 02:16:45

你不能。但是,如果使用该函数而比较器没有它,您的编译将失败,这或多或少是您想要发生的情况。是的,就像其他人指出的那样,您想将静态称为静态。

You can't. But if use the function and the Comparer doesn't have it, your compile will fail and this is more or less what you want to happen. And yes, like others pointed out you want to call static as static.

£冰雨忧蓝° 2024-08-23 02:16:45

您是否尝试这样做:

   int res = Comparer::compare(key1, key2);

在 C++ 中,静态函数可以通过两种方式调用:

object.static_method(); // use dot operator

classname::static_method(); // use scope resolution operator

Did you try doing:

   int res = Comparer::compare(key1, key2);

In C++ Static functions can be called in two ways:

object.static_method(); // use dot operator

classname::static_method(); // use scope resolution operator
向地狱狂奔 2024-08-23 02:16:45

Michael 已经提到如果 Comparer 没有所需的成员函数。

但是,如果您更担心简洁的错误消息,请使用类似 this 来检测类是否具有必需的成员函数并将其与诸如 Boost.StaticAssert

template<typename K, typename T, typename Comparer>
class AVLTree
{
    BOOST_STATIC_ASSERT(HasCompareMethod<Comparer>::has);
    //...
};

Michael already mentioned that this will not compile if Comparer doesn't have the required member function.

If however you're more worried about concise error messages, use something like this to detect if the class has a required member function and combine it with something like Boost.StaticAssert:

template<typename K, typename T, typename Comparer>
class AVLTree
{
    BOOST_STATIC_ASSERT(HasCompareMethod<Comparer>::has);
    //...
};
万劫不复 2024-08-23 02:16:45

它必须是Comparer::Compare,对吧? (因为您正在调用类型上的静态函数)。

您的 Comparer 类必须定义如下:

template<typename K>
class Comparer
{
public:
    static bool Compare(K key, K key)
    {
        return true;
    }
};

It would have to be Comparer::Compare, right? (Since you are calling a static function on a type).

Your Comparer class would have to be defined as follows:

template<typename K>
class Comparer
{
public:
    static bool Compare(K key, K key)
    {
        return true;
    }
};
漫雪独思 2024-08-23 02:16:45

据我了解,您正在寻找更好的错误消息,以防模板参数不符合模板主体的要求。该语言没有内置的特殊机制,但人们使用库来近似它。请参阅 Boost 概念检查

I understand it you're looking for a better error message in case the template parameter doesn't fit the requirements of the template body. the language doesn't have an special mechanism for that built in, but people approximate it using libraries. see Boost Concept Check

任性一次 2024-08-23 02:16:45

对此进行编译时断言的松散方法是获取 Comparer::compare 的地址并将其分配给声明为 int(K, K) *func 的变量。

如果它是静态函数,则该分配将起作用,但如果它是成员函数,则该分配将不起作用。

我只是贡献这个,但我会采取使用 boost 习语的方法,因为这是手工制作的,可以这么说。

The loose approach of having a compile time assertion around this is to take the address of Comparer::compare and assign it to a variable declared as int(K, K) *func.

That assignment will work if it's a static function, but will not work if it's a member function.

I am just contributing this, but I would take the approach of using the boost idioms as this is hand-rolled, so to speak.

海之角 2024-08-23 02:16:45

这是一种更惯用和通用的方法:

template<typename K, typename T>
class AVLTree
{
   ...
   template <typename Comparer>
   void foo(Comparer cmp) {
       ...
       int res = cmp(key1, key2);
       ...
   }
   ...
};

Comparer 不应该是定义静态 Compare 方法的类型。它应该是一个可以用函数调用语法调用的类型。这允许您使用函数对象的函数指针,并且允许您重用标准库中或几乎任何其他重要的 C++ 应用程序中已定义的比较器。它允许您在 C++0x 中添加 lambda 时使用它们。

至于强制 Comparer 按预期行事? int res = cmp(key1, key2); 行已经确保了这一点。如果尝试传递无法以这种方式调用的类型,则会出现编译错误。

您的原始代码中的情况也是如此。如果您传递的类型没有静态 Compare 方法,则会出现编译错误。所以你原来的代码已经解决了这个问题。

Here's a more idiomatic and generic approach:

template<typename K, typename T>
class AVLTree
{
   ...
   template <typename Comparer>
   void foo(Comparer cmp) {
       ...
       int res = cmp(key1, key2);
       ...
   }
   ...
};

Comparer should not be a type that defines a static Compare method. It should be a type which can be called with function call syntax. That allows you to use function pointers of function objects, and it allows you to reuse the comparers already defined in the standard library, or in pretty much any other nontrivial C++ application. It allows you to use lambdas when they're added in C++0x.

As for forcing Comparer to behave as expected? The line int res = cmp(key1, key2); already ensures that. If you try to pass a type that can't be called in this way, you get a compile error.

The same was the case in your original code. If you passed a type that didn't have a static Compare method, you'd get a compile error. So your original code already solved the problem.

和我恋爱吧 2024-08-23 02:16:45

正如已经指出的,您不能强制 Compare 有一个静态成员 compare。如果您的比较器没有实现它,您只会收到编译器错误。

如果你像这样实现AVLTree,那么将Comparer声明为模板模板参数会更优雅:

template <typename K>
class DefaultComparer
{
public:
    static bool compare(K k1, K k2)
    { return k1 == k2; }
};

template <typename K>
class MyComparer : public DefaultComparer<K>
{
public:
    static bool compare(K k1, K k2)
    { return k1 <= k2; }
};

template <typename K>
class InvalidComparer
{
public:
    static bool bar(K k1, K k2)
    { return k1 != k2; }
    // Doesn't implement compare()
};

// Compare is a template template paramenter with default template argument
// DefaultComparer
template <typename K, template <typename K> class Comparer = DefaultComparer>
class AVLTree
{
    K k1, k2;
public:
    AVLTree() : k1(0), k2(0) { } // ctor
    bool foo();
};

// Definiton of AVLTree::foo()
template <typename K, template <typename K> class Comparer>
bool AVLTree<K, Comparer>::foo()
{
    return Comparer<K>::compare(k1, k2);
}

int main(int argc, char *argv[])
{
    // Without template template parameters you 
    // would have to use AVLTree<int, DefaultComparer<int> >
    AVLTree<int> avltree;

    // instead of AVLTree<int, MyCompare<int> >
    AVLTree<int, MyComparer> avltree2;

    // Calling foo() will generate a compile error. 
    // But if you never call avltree3.foo() this will compile!
    AVLTree<int, InvalidComparer> avltree3;

    avltree.foo(); // calls DefaultComparer::compare
    avltree2.foo(); // calls MyComparer::compare
    avltree3.foo(); // fails to compile
}

请参阅:http://codepad.org/OLhIPjed

As already pointed out, you can't force Compare to have a static member compare. If your comparer doesn't implement it, you just get an compiler error.

If you implement AVLTree like this it would be more elegant to declare Comparer as a template template parameter:

template <typename K>
class DefaultComparer
{
public:
    static bool compare(K k1, K k2)
    { return k1 == k2; }
};

template <typename K>
class MyComparer : public DefaultComparer<K>
{
public:
    static bool compare(K k1, K k2)
    { return k1 <= k2; }
};

template <typename K>
class InvalidComparer
{
public:
    static bool bar(K k1, K k2)
    { return k1 != k2; }
    // Doesn't implement compare()
};

// Compare is a template template paramenter with default template argument
// DefaultComparer
template <typename K, template <typename K> class Comparer = DefaultComparer>
class AVLTree
{
    K k1, k2;
public:
    AVLTree() : k1(0), k2(0) { } // ctor
    bool foo();
};

// Definiton of AVLTree::foo()
template <typename K, template <typename K> class Comparer>
bool AVLTree<K, Comparer>::foo()
{
    return Comparer<K>::compare(k1, k2);
}

int main(int argc, char *argv[])
{
    // Without template template parameters you 
    // would have to use AVLTree<int, DefaultComparer<int> >
    AVLTree<int> avltree;

    // instead of AVLTree<int, MyCompare<int> >
    AVLTree<int, MyComparer> avltree2;

    // Calling foo() will generate a compile error. 
    // But if you never call avltree3.foo() this will compile!
    AVLTree<int, InvalidComparer> avltree3;

    avltree.foo(); // calls DefaultComparer::compare
    avltree2.foo(); // calls MyComparer::compare
    avltree3.foo(); // fails to compile
}

see: http://codepad.org/OLhIPjed

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文