MrB*_*app 4 c++ templates sfinae c++14
我有一个模板类,其中有一个方法,模板参数指示该方法的输入和输出,如下所示:
template <typename In, typename Out>
class Foo
{
Out fn(const In& in)
{
Out out;
return out;
}
}
Run Code Online (Sandbox Code Playgroud)
所以我尝试了这个,但是当试图void用于任何一个In或那个时,会出现(可能很明显)错误Out.所以我尝试添加多个方法,这些方法是这个主题的变体,希望它们的替换能够启用相关功能并禁用无效功能:
template <std::enable_if_t<std::is_void<InputType>::value>* = nullptr>
OutputType fn()
{
OutputType out;
return out;
}
template <std::enable_if<(!std::is_void<OutputType>::value) && (!std::is_void<InputType>::value)>* = nullptr>
OutputType fn(InputType& t)
{
OutputType out;
return out;
}
template <std::enable_if<std::is_void<OutputType>::value>* = nullptr>
void fn(InputType& t)
{}
Run Code Online (Sandbox Code Playgroud)
这让我回到了"无效参考无效"领域,或者是碰撞签名.
我应该如何优雅地处理这些条件,以便从模板中只创建以下签名之一:
/*In == void && Out != void*/
Out fn(/* no input here to keep compiler happy*/) { return Out; }
/*In != void && Out != void, standard case*/
Out fn(const In& in) { return Out; }
/*In != void && Out == void*/
void fn(const In& in) { /* No returns here to keep compiler happy*/; }
Run Code Online (Sandbox Code Playgroud)
您可以使用部分特化来提供Foofor In和Outvoid的实现,以及当两者都为void时的显式特化.
语法如下(注意Foo表示这是主类模板的特殊化后的尖括号Foo)
template<typename Out>
struct Foo<void, Out> // specialisation for only In = void
{ ... };
template<typename In>
struct Foo<In, void> // specialisation for only Out = void
{ ... };
template<>
struct Foo<void, void> // specialisation for both In and Out = void
{ ... };
Run Code Online (Sandbox Code Playgroud)
这是一个例子:
#include <iostream>
// primary class template
template <typename In, typename Out>
struct Foo {
Out fn(const In& in) { return Out{}; }
};
// partial specialisation for when In=void
template<typename Out>
struct Foo<void, Out> {
Out fn() { return Out{}; }
};
// partial specialisation for when Out=void
template<typename In>
struct Foo<In, void> {
void fn(const In& in) { }
};
// explicit specialisation for when both In=void and Out=void
template<>
struct Foo<void, void> {
void fn() { }
};
int main() {
Foo<int, double> f;
f.fn(5);
Foo<void, void> g;
g.fn();
Foo<void, int> h;
h.fn();
Foo<int, void> i;
i.fn(5);
return 0;
}
Run Code Online (Sandbox Code Playgroud)