Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 处理条件编译的多个条件的最佳方法_C++_Templates_C++14_Sfinae - Fatal编程技术网

C++ 处理条件编译的多个条件的最佳方法

C++ 处理条件编译的多个条件的最佳方法,c++,templates,c++14,sfinae,C++,Templates,C++14,Sfinae,我有一个模板类,它有一个方法,其中模板参数指示该方法的输入和输出,如下所示: template <typename In, typename Out> class Foo { Out fn(const In& in) { Out out; return out; } } 这让我回到了“无效引用无效”的领域,或者签名冲突 我应该如何优雅地处理这些条件,以便仅从模板创建以下签名之一: /*In == void &&

我有一个模板类,它有一个方法,其中模板参数指示该方法的输入和输出,如下所示:

template <typename In, typename Out>
class Foo
{
    Out fn(const In& in)
    {
        Out out;
        return out;
    }
}
这让我回到了“无效引用无效”的领域,或者签名冲突

我应该如何优雅地处理这些条件,以便仅从模板创建以下签名之一:

/*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*/; }
In
Out
中的任何一个无效时,以及当这两个都无效时,可以使用提供
Foo
的实现

语法如下(注意
Foo
后面的尖括号,表示这是主要
Foo
类模板的特殊化)

模板
struct Foo//仅适用于In=void的专业化
{ ... };
模板
struct Foo//仅针对Out的专业化=无效
{ ... };
模板
struct Foo//In和Out的专业化=无效
{ ... };
以下是一个例子:

#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;
}
#包括
//主类模板
模板
结构Foo{
Out fn(const In&In){return Out{};}
};
//在=无效时的部分专业化
模板
结构Foo{
Out fn(){return Out{};}
};
//部分专业化的时间=无效
模板
结构Foo{
void fn(const In&In){}
};
//当In=void和Out=void时的明确专业化
模板
结构Foo{
void fn(){}
};
int main(){
福福;
f、 fn(5);
傅g,;
g、 fn();
福华;
h、 fn();
富一;
i、 fn(5);
返回0;
}

返回值和输入值是不同的问题,您可以独立解决它们

首先,我建议您切换模板类型的顺序:First
Out
,next
In

这是因为如果在输入类型的可变列表中变换

template <typename Out, typename ... Ins>
struct Foo { /* ... */ };
其中
someVal
Out
类型,当
Out
不是
void
时,如果
Out
void
,则为另一种类型(例如:
int

因此,如果您定义一个类型traits
deVoid
,如下所示

template <typename T>
struct deVoid
 { using type = T; };

template <>
struct deVoid<void>
 { using type = int; }; // a fake not-void type

template <typename T>
using deVoid_t = typename deVoid<T>::type;
  deVoid_t<Out> out {};
template <typename Out, typename ... Ins>
struct Foo
 {
   Out fn (Ins const & ... ins)
    {
      deVoid_t<Out> out {};

      return (Out)out;
    }
 };
然后以这种方式返回

  return (Out)out;
Out
void
时,该功能也有效

因此,您可以编写
Foo
,如下所示

template <typename T>
struct deVoid
 { using type = T; };

template <>
struct deVoid<void>
 { using type = int; }; // a fake not-void type

template <typename T>
using deVoid_t = typename deVoid<T>::type;
  deVoid_t<Out> out {};
template <typename Out, typename ... Ins>
struct Foo
 {
   Out fn (Ins const & ... ins)
    {
      deVoid_t<Out> out {};

      return (Out)out;
    }
 };
你可以。但我不建议你走这条路。
template <typename T>
struct deVoid
 { using type = T; };

template <>
struct deVoid<void>
 { using type = int; }; // a fake not-void type

template <typename T>
using deVoid_t = typename deVoid<T>::type;

template <typename Out, typename ... Ins>
struct Foo
 {
   Out fn (Ins const & ... ins)
    {
      deVoid_t<Out> out {};

      return (Out)out;
    }
 };

int main ()
 {
   Foo<int, int>         f; f.fn(42);
   Foo<void>             g; g.fn();
   Foo<int>              h; h.fn();
   Foo<void, int>        i; i.fn(42);
   Foo<void, int, long>  j; j.fn(42, 84L);
 }