使模板类方法参数类型与类模板参数相同(包括void)

问题描述 投票:0回答:1

想要使类方法具有与类模板参数匹配的签名,例如,对于一个类,如果 T 不为 void,则为 Class::Method(T t);如果 T 为 void,则为 Class::Method() .

编译下面尝试的代码,如果 T 为 void,则两种方法都存在。 我不明白为什么同样使用 enable_if 适用于 foo 但不适用于该版本的 print

#include <iostream>
using namespace std;

template <typename T>
struct S
{
    template <typename U = T>
    std::enable_if_t<std::is_void_v<U>, void>
    print(void) { cout << "print void"  << endl; }

    template <typename U = T>
    std::enable_if_t<not(std::is_void_v<U>), void>
    print(U x) { cout << "print not void " << x << endl; }

    template <typename U = T>
    std::enable_if_t<not(std::is_void_v<U>), void>
    foo() {};

    // ... rest of class
};

int main()
{
    S<int> i;
    i.print(1);
    // i.print();  // is disabled

    S<void> v;
    v.print();
    v.print(2); // should be disabled but is not
    v.foo(); // same enable_if use disabled this method
}
c++ templates enable-if
1个回答
0
投票
v.foo<int>()

您认为

foo
的 void 版本上的
S
版本不存在,这是错误的。 上面的代码将完美运行。

您所显示的是默认模板参数选择了一个不存在的版本。

print
的情况下,您提供默认模板参数 - 但您也允许它们显式传递(即
.print<double>(1)
)或推导(如
.print(2)
中)。

在这两种情况下,这都会导致

U
类型不是
T
,因此不是
void

至少有两种方法。 您可以阻止推导(让

foo
样式不存在以适用于
print
),甚至可以阻止传递显式参数(防止调用
foo<int>()
)。 其次,您还可以使用
requires
,它更干净,但需要较新版本的 C++。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.