Enable_if'ed 模板化模板构造函数的类型签名?

发布于 2024-10-19 14:47:49 字数 829 浏览 4 评论 0原文

我通常声明我的类和模板,然后定义它们的方法(当然,在同一个头文件中)。我只是发现这样更容易阅读。好吧,我遇到过一种情况,我无法找出在类外定义中使用的工作类型签名。这是我正在做的事情的一个简化示例,它说明了问题:

template <class T>
struct Foo
  {
    Foo(T a, T b);

    template 
      < class Iterator
      , enable_if< is_iterator<Iterator> >
      >
    Foo
      ( Iterator first
      , Iterator last
      );
  };

template <class T>
Foo<T>::Foo(T a, T b)
{ ... }

template <class T>
template
  < class U
  , WHAT_GOES_HERE?
  >
Foo<T>::Foo(U f, U l)
{ ... }

我在 WHAT_GOES_HERE 槽中尝试了很多方法来尝试获取匹配的签名,但一直失败。我需要enable_if来区分传入两个T类型对象的情况和传入一对迭代器的情况。如果模板化构造函数是在主模板内定义的,则代码可以正常工作(这就是代码当前的执行方式),但我宁愿将定义移到声明之外。

编辑:我应该提到我不能只重复使用enable_if<...>在定义中,因为enable_if<...>;为其类型分配一个默认值,您不能在不是声明的定义中执行此操作。

I usually declare my classes and templates, and then define their methods after (in the same header file, of course). I just find it easier to read that way. Well, I've come across a case where I can't figure out a working type signature to use in an out-of-class definition. Here's a simplified example of what I'm doing, that illustrates the problem:

template <class T>
struct Foo
  {
    Foo(T a, T b);

    template 
      < class Iterator
      , enable_if< is_iterator<Iterator> >
      >
    Foo
      ( Iterator first
      , Iterator last
      );
  };

template <class T>
Foo<T>::Foo(T a, T b)
{ ... }

template <class T>
template
  < class U
  , WHAT_GOES_HERE?
  >
Foo<T>::Foo(U f, U l)
{ ... }

I have tried a number of things in the WHAT_GOES_HERE slot to try to get a matching signature, and I keep failing. I need the enable_if to distinguish the case where one passes in two objects of type T, and when one passes in a pair of Iterators. The code works fine if the templated constructor is defined inside the main template, which is how the code currently does it, but I'd much rather move the definition outside the declaration.

EDIT: I should mention that I can't just re-use enable_if<...> in the definition, because enable_if<...> assigns a default value for its type, which you cannot do in a definition that isn't also a declaration.

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

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

发布评论

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

评论(4

我不在是我 2024-10-26 14:47:49

我不会那样做。以下是我要做的更改:

template <class T>
struct Foo
  {
    Foo(T a, T b);

    template 
      < class Iterator
      >
    Foo
      ( Iterator first
      , Iterator last
      , typename enable_if<is_iterator<Iterator> >::type* = 0
      );
  };

template <class T>
Foo<T>::Foo(T a, T b)
{ ... }

template <class T>
template
  < class U
  >
Foo<T>::Foo(U f, U l, typename enable_if< is_iterator<U> >::type*)
{ ... }

这直接来自 enable_if 的文档。

I wouldn't do it that way. Here's the changes I would make:

template <class T>
struct Foo
  {
    Foo(T a, T b);

    template 
      < class Iterator
      >
    Foo
      ( Iterator first
      , Iterator last
      , typename enable_if<is_iterator<Iterator> >::type* = 0
      );
  };

template <class T>
Foo<T>::Foo(T a, T b)
{ ... }

template <class T>
template
  < class U
  >
Foo<T>::Foo(U f, U l, typename enable_if< is_iterator<U> >::type*)
{ ... }

This is straight out of the documentation for enable_if.

烧了回忆取暖 2024-10-26 14:47:49

这就是你想要实现的目标吗? [我没有 is_iterator 类型特征,因此我使用 C++0x 类型特征和实用程序库重新设计了您的示例。它应该以与 TR1 和 Boost 库相同的方式工作。]

#include <utility>
#include <type_traits>

template <typename T>
struct S
{
    // Constructor (1)
    S(T, T); 

    // Constructor (2)
    template <typename U>
    S(U, U, typename std::enable_if<std::is_integral<U>::value>::type* = 0);
};

template <typename T>
S<T>::S(T, T)
{ }

template <typename T>
template <typename U>
S<T>::S(U, U, typename std::enable_if<std::is_integral<U>::value>::type*)
{ }

int main()
{
    S<double> a(1.0, 2.0); // uses (1)
    S<double> b(1, 2);     // uses (2)
}

Is this what you are trying to accomplish? [I don't have an is_iterator type trait, so I've reworked your example using the C++0x type traits and utility libraries. It should work the same way with the TR1 and Boost libraries.]

#include <utility>
#include <type_traits>

template <typename T>
struct S
{
    // Constructor (1)
    S(T, T); 

    // Constructor (2)
    template <typename U>
    S(U, U, typename std::enable_if<std::is_integral<U>::value>::type* = 0);
};

template <typename T>
S<T>::S(T, T)
{ }

template <typename T>
template <typename U>
S<T>::S(U, U, typename std::enable_if<std::is_integral<U>::value>::type*)
{ }

int main()
{
    S<double> a(1.0, 2.0); // uses (1)
    S<double> b(1, 2);     // uses (2)
}
二智少女 2024-10-26 14:47:49

您可以做的最简单的事情是:

template<class Iterator>
Foo
  ( Iterator first
  , typename enable_if<is_iterator<Iterator>, Iterator>::type last
  );

The simplest you can do is:

template<class Iterator>
Foo
  ( Iterator first
  , typename enable_if<is_iterator<Iterator>, Iterator>::type last
  );
酒废 2024-10-26 14:47:49
template <class T>
struct Foo
  {
    Foo(T a, T b);

    template <class Iterator
      ,       class = typename std::enable_if
                       <is_iterator<Iterator>::value>
                       ::type
      >
    Foo
      ( Iterator first
      , Iterator last
      );
  };

template <class T>
Foo<T>::Foo(T a, T b)
{  }

template <class T>
template
  < class U
  , class >
Foo<T>::Foo(U f, U l)
{  }
template <class T>
struct Foo
  {
    Foo(T a, T b);

    template <class Iterator
      ,       class = typename std::enable_if
                       <is_iterator<Iterator>::value>
                       ::type
      >
    Foo
      ( Iterator first
      , Iterator last
      );
  };

template <class T>
Foo<T>::Foo(T a, T b)
{  }

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