我想让模板类限制一个像这个例子的重载方法:
template<int N>
class foo {
public:
void add(int a, int* b) {*b = a + N;}
int add(std::enable_if<N == 0, int> a, int b) {return a + b}
}
(更改示例以反映原始示例中不存在的并发症。)
但是,我使用的是Visual Studio,它对SFINAE(以及enable_if)的支持仍然不是很好。 (我不确定它是否适用于这个简单的例子;在我的实际情况中,我在类引用上使用std::enable_if
并使用该类的成员,但它不起作用。)答案to this(我得到的错误消息基本上相同)建议使用标签调度作为替代方案,但我不确定如果我希望函数根本不可用那些参数类型那会怎样,或者如果我想以这种方式重载构造函数。
答案 0 :(得分:3)
需要将其制作成功能模板。并且enable_if
中的条件需要依赖于函数模板的模板参数,以便它不会被提前替换。
template<int M = N,
class = typename std::enable_if<M == 0>::type>
int add(int a, int b) { return a + b; }
答案 1 :(得分:0)
通常我会看到std::enable_if
与返回类型
template<int N>
class foo {
public:
int add(int a)
{return a + N;}
template <int M = N>
typename std::enable_if<M == 0, int>::type add(int a, int b)
{return a + b}
}
这没有用?
另一种方法可以是使用仅定义bar
的基类(add(int, int)
,仅在所需的专门化中)。
template <int N>
struct bar
{ int add (int a, int b) = delete; };
template <>
struct bar<0>
{ int add (int a, int b) { return a + b; } };
template <int N>
struct foo : public bar<N>
{ using bar<N>::add; void add (int a, int * b) { *b = a + N; } };
int main()
{
foo<0> f0;
foo<1> f1;
int b { 0 };
f0.add(1, &b);
f0.add(1, 2);
f1.add(1, &b);
//f1.add(1, 2); // compilation error
}
请注意using bar<N>::add
中的foo
是必需的,否则add(int)
foo
会隐藏add(int, int)
中的bar
。< / p>
此using
将int add (int a, int b) = delete;
强加于bar<N>
的通用版本。
如果两个函数的名称不同,对于包含2个整数参数的版本,请说add2()
,示例变为如下
template <int N>
struct bar
{ };
template <>
struct bar<0>
{ int add2 (int a, int b) { return a + b; } };
template <int N>
struct foo : public bar<N>
{ void add (int a, int * b) { *b = a + N; } };
int main()
{
foo<0> f0;
foo<1> f1;
int b { 0 };
f0.add(1, &b);
f0.add2(1, 2);
f1.add(1, &b);
//f1.add2(1, 2); // compilation error
}
答案 2 :(得分:0)
没有简单的代码转换是合法的。模板类的方法签名必须合法。
template<class D, bool> // false case
struct add_base {
void add(int* a, int b) {*a += b}
D*self(){return static_cast<D*>(this);}
D const*self()const{return static_cast<D const*>(this);}
};
template<class D>
struct add_base<D,true>:add_base<D,false> {
using base=add_base<D,false>;
using base::self;
using base::add; // for overload resolution
int add(int a, int b) {return a + b}
};
template<int N>
class foo: add_base<foo<N>, N==0> {
using base = add_base<foo<N>, N==0>;
template<class D, bool b>
friend class add_base<D, b>;// may be a syntax error here.
public:
using base::add;
};
这里我假设真正的add
想要使用this
;在这种情况下,在其实现中使用self()
。
还有其他技术使用带有默认值的模板参数,但是在严格阅读标准下它们的合法性是值得怀疑的。问题在于标准要求所有模板函数都具有有效的特化,并且大多数这些技术都违反了该规则。对于它们可能合法的标准有不同的读数。
您还可以等待c++2a个概念。