为不同版本的功能模板标识不同的默认参数

时间:2018-10-17 06:35:21

标签: c++ templates

首先我有一个功能模板

template<typename S>
void foo(const S & s, int a = 1, double b = 2)

然后我想提供专门的实现,因为S是一个STL容器。特别是,我想提供不同的默认参数。

由于C ++中不允许部分函数模板专门化,因此我只重载了foo。说

template<typename T>
void foo(const vector<T> & s, int a = 3, double b = 4)

目前一切都很好。

现在,我想编写一个仅接受一个参数partial_foo的函数模板double b = 6,然后让编译器根据{{ 1}}它调用。 请注意,afoo的呼叫签名中位于b之后。

a

理想情况下,foo将具有默认参数template<typename S> foo_partial(const S & s, double b = 6) ,而foo_partial(int)将具有默认参数int a = 1

我的问题是:我可以执行此操作(即如何实现foo_partial(vector<int>())),还是考虑到int a = 3的设计,是否有任何解决方法?

例如,请考虑

foo_partial

输出为

foo

我的问题等同于:我可以使用#include <bits/stdc++.h> using namespace std; template<typename S> void foo(const S & s, int a = 1, double b = 2) { printf("foo(S) with a = %d, b = %.0f\n", a, b); } template<typename T> void foo(const vector<T> & t, int a = 3, double b = 4) { printf("foo(vector<T>) with a = %d, b = %.0f\n", a, b); } template<typename S> void foo_partial(const S & s, double b = 6) { // how to implement foo_partial so that ____ corresponds to // the default argument in the proper version of foo? int ____ = 5; foo(s, ____, b); } int main() { foo_partial(0); foo_partial(vector<int>()); } 的设计做任何事情或任何替代方法,以使输出为

foo(S) with a = 5, b = 6
foo(vector<T>) with a = 5, b = 6

谢谢您的时间!

2 个答案:

答案 0 :(得分:2)

不包括#include <bits/stdc++.h>,它是非标准的,在大多数平台上均不起作用。

也建议不要使用

using namespace std,因为它会导致将来的标准添加与您自己的代码之间发生冲突。

解决问题的一种方法是将默认参数移至具有特殊功能的模板类:

#include <vector>
#include <cstdio>

using std::vector;

template <typename S>
struct defaults
{
    static constexpr int a = 1;
    static constexpr double b = 2;
};

template <typename T>
struct defaults<vector<T>>
{
    static constexpr int a = 3;
    static constexpr double b = 4;
};

template<typename S>
void foo(const S & s, int a = defaults<S>::a, double b = defaults<S>::b)
{
    printf("foo(S) with a = %d, b = %.0f\n", a, b);
}

template<typename T>
void foo(const vector<T> & t, int a = defaults<vector<T>>::a, double b = defaults<vector<T>>::b)
{
    printf("foo(vector<T>) with a = %d, b = %.0f\n", a, b);
}

template<typename S>
void foo_partial(const S & s, double b = 6)
{
    foo(s, defaults<S>::a, b);
}

int main()
{
    foo_partial(0);
    foo_partial(vector<int>());
}

如果仅使用foo来更改默认参数,则不再需要函数重载。

答案 1 :(得分:0)

您还可以使用所谓的命名参数惯用法,它更通用且可扩展:

#include <iostream>
#include <vector>

template <typename T> class Foo {
  int a_; double b_; const T& value_;
public:
  Foo(const T& value) : value_(value), a_(1), b_(2.0) { }
  Foo& set_a(int a) { a_ = a; return *this; }
  Foo& set_b(double b) { b_ = b; return *this; }
  void operator()() { std::cout << "foo(T) with a = " << a_ << " and b = " << b_ << std::endl; }
};

template <typename T> class Foo<std::vector<T>> {
  int a_; double b_; const std::vector<T>& value_;
public:
  Foo(const std::vector<T>& value) : value_(value), a_(3), b_(4.0) { }
  Foo& set_a(int a) { a_ = a; return *this; }
  Foo& set_b(double b) { b_ = b; return *this; }
  void operator()() { std::cout << "foo(std::vector<T>) with a = " << a_ << " and b = " << b_ << std::endl; }
};

template <typename T>
void foo_partial(const T& value, double b = 6) { Foo<T>(value).set_b(b)(); }

int main() {
  foo_partial(0);
  foo_partial(std::vector<int>{});
}

哪个打印出来:

foo(T) with a = 1 and b = 6    
foo(std::vector<T>) with a = 3 and b = 6