在类模板实例化中明确使用某些参数的默认值

iFr*_*cht 22 c++ templates default c++11

类模板可以有多个参数都具有默认值.

template<typename UnderlyingT0 = int, typename UnderlyingtT1 = long, typename StringT = std::string>
struct options;
Run Code Online (Sandbox Code Playgroud)

使用默认参数来设置模板很简单:

options<> my_default_options;
Run Code Online (Sandbox Code Playgroud)

但是,如果我想更改参数的子集呢?

options<int, int, std::wstring> wstring_options;
Run Code Online (Sandbox Code Playgroud)

int第一个参数的默认值并不明显,而第二个参数则不是.有没有类似的东西

options<default, int, std::wstring> wstring_options;
Run Code Online (Sandbox Code Playgroud)

在C++中?

Rei*_*ica 19

不,标准C++中没有任何内容可以实现这一点.@FlorisVelleman在评论中指出的一个选择是引入一个别名模板:

template <class UnderlyingT1, class StringT = std::string>
using options_defT0 = options<int, UnderlyingT1, StringT>;
Run Code Online (Sandbox Code Playgroud)

这样做的缺点是必须明确复制UnderlyingT0别名定义中的默认参数,但至少它只在一个地方复制.

许多Boost库使用另一种选择.他们引进了特殊的标记use_default,使默认值.像这样的东西:

struct use_default {};

template<typename UnderlyingT0 = use_default, typename UnderlyingtT1 = use_default, typename StringT = use_default>
struct options
{
  using RealUnderlyingT0 = typename std::conditional<
    std::is_same<UnderlyingT0, use_default>::value,
    int,
    UnderlyingT0
  >::type;

  using RealUnderlyingT1 = typename std::conditional<
    std::is_same<UnderlyingT1, use_default>::value,
    long,
    UnderlyingT1
  >::type;

  using RealStringT = typename std::conditional<
    std::is_same<StringT, use_default>::value,
    std::string,
    StringT
  >::type;
};
Run Code Online (Sandbox Code Playgroud)

这里的缺点是1.你不能通过查看模板声明来告诉默认参数,options<>而且options<int, long, std::string>它们是不同的类型.

前者可以通过良好的文档来修复,后者可以通过明智地使用转换函数和基类来帮助.


Seb*_*edl 14

没有办法直接重用默认参数.您可以使用Floris的注释作为为常见用途提供缩写的方法,但模板别名仍将重复默认值.

或者,可以设置options结构以允许切换参数:

template <typename UnderlyingT0 = int,
          typename UnderlyingT1 = long,
          typename StringT = std::string>
struct options {
  template <typename NewT0>
  using WithT0 = options<NewT0, UnderylingT1, StringT>;
  template <typename NewT1>
  using WithT1 = options<UnderylingT0, NewT1, StringT>;
  template <typename NewStringT>
  using WithStringT = options<UnderylingT0, UnderylingT1, NewStringT>;
};
Run Code Online (Sandbox Code Playgroud)

然后用它作为

options<>::WithT1<int>::WithStringT<std::wstring>
Run Code Online (Sandbox Code Playgroud)


Tar*_*ama 6

如果所有模板参数都有默认值,例如,您可以创建一个帮助程序结构来为您提取它们.

template <class T, size_t N>
struct default_for_helper;

template <template <typename...> class T, size_t N, typename... Args>
struct default_for_helper<T<Args...>, N>
{
    using type = std::tuple_element_t<N, std::tuple<Args...>>;
};

template <template <typename...> class T, size_t N>
using default_for = typename default_for_helper<T<>, N>::type;
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它:

options<default_for<options,0>, int, std::string> o;
Run Code Online (Sandbox Code Playgroud)