【问题标题】:enable_if class member function with separate definitionenable_if 具有单独定义的类成员函数
【发布时间】:2018-03-05 11:52:27
【问题描述】:

我正在使用enable_if 类成员函数来迭代变分模板参数。这是一个最小的例子(没有实际的可变参数)

#include <iostream>

template<int size> class Test {
    public:
        template<int i = 0> typename std::enable_if<i == size, void>::type test() {}

        template<int i = 0> typename std::enable_if<i < size, void>::type test() {
            std::cout << "cycle: " << i << '\n';
            test<i + 1>();
        }
};

int main(int, char**) {
    Test<10> a;
    a.test<>();
}

它工作得很好,但现在我遇到了依赖问题,并决定将声明和定义分开。我试过这个:

#include <iostream>

template<int size> class Test {
    public:
        template<int i = 0> void test();
};

template<int size>
template<int i> typename std::enable_if<i == size, void>::type Test<size>::test() {}

template<int size>
template<int i> typename std::enable_if<(i < size), void>::type Test<size>::test() {
    std::cout << "cycle: " << i << '\n';
    test<i + 1>();
}

int main(int, char**) {
    Test<10> a;
    a.test<>();
}

但是 GCC 说 error: out-of-line definition of 'test' does not match any declaration in 'Test&lt;size&gt;'。我设法通过包含test 两种情况的定义来使其工作。我的问题是:为什么这不起作用?编译器不应该只找到任何i 的声明之一吗?提前感谢您的帮助!

【问题讨论】:

  • 如果你想在编译时迭代数字,你可能会对std::index_sequence 替换std::enable_if感兴趣。 that 之类的东西(也可以在 C++11 中完成)
  • 那太好了,我会切换到那个。非常感谢! (我从来没有见过省略号的用法,真的很酷)

标签: c++ c++11 enable-if class-members


【解决方案1】:
template<int i = 0> 
typename std::enable_if<i == size, void>::type test() { }

template<int i = 0> 
typename std::enable_if<i < size, void>::type test() { /* ... */ }

上面的两个成员函数完全不同,只是碰巧同名test。它们有不同的签名,必须单独声明。类似于写法:

template<int i = 0> 
int test() { }

template<int i = 0> 
float test() { /* ... */ }

您是否希望能够在您的类定义中为这两个声明都提供一个声明?

【讨论】:

  • 好吧,那我真的不明白enable_if 做了什么。我认为当条件为真时,它只是成为类型(在这种情况下为 void),而当条件失败时,它就消失了。所以他们有不同的返回类型?
  • @mbtg:您对enable_if 的理解是正确的,但它并没有什么特别之处——它只是一个与其他类型一样的返回类型。由于 SFINAE,它消失了,enable_if 并不是什么神奇的东西。您仍然有 两个 具有 两个 不同返回类型的不同函数 - 它们都恰好是 enable_if 的不同实例化,但这并不意味着这些函数被神奇地捆绑在一起在一起。
  • 我希望在那里保存一些代码,但我想我不能。非常感谢您的帮助!
【解决方案2】:

您需要在类中添加具有匹配签名的声明

#include <iostream>

template<int size> class Test {
    public:
        template<int i = 0> typename std::enable_if<i == size, void>::type test();
    template<int i = 0> typename std::enable_if<i < size, void>::type test();
};

template<int size>
template<int i> typename std::enable_if<i == size, void>::type Test<size>::test() {}

template<int size>
template<int i> typename std::enable_if<(i < size), void>::type Test<size>::test() {
    std::cout << "cycle: " << i << '\n';
    test<i + 1>();
}

int main(int, char**) {
    Test<10> a;
    a.test<>();
}

【讨论】:

  • 你必须将(i &lt; size)改为i&lt;size才能编译
猜你喜欢
  • 1970-01-01
  • 2022-11-11
  • 2012-01-22
  • 2012-08-07
  • 1970-01-01
  • 2012-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多