从用户代码注入默认模板参数类型

Inject default template argument type from user code

有没有一种方法可以为模板的模板成员函数“注入”默认类型class“在”所述模板成员函数的定义之后?

与此基本相似(无法编译),因此我可以在库外指定 NS::DefaultZ 的默认类型),其中模板 class S及其成员函数模板定义:

// In library
namespace NS {}

template<typename T>
struct S {
  template<typename X, typename Z = NS::Default>
  void foo(X x, Z z = Z{}) {}
};


// In user code
namespace NS {
  using Default = int;
}

S<SomeClass> s;
s.foo(3.14); // z == int(0)

我想我曾经有过这样的代码用于后来指定的类型特征,但是已经有一段时间了,我的模板 foo 有点生疏了。

主要目标是能够仅使用一个参数调用 S::foo 并让它使用具有默认类型的默认参数,默认类型不是由库指定,而是由使用代码指定。

通过 class 模板注入该类型当然是一种选择,但不是我所要求的。所以我不想做:

// library
template<typename T, typename ZDefault>
struct S {
  template<typename X, typename Z = ZDefault>
  void foo(X x, Z z = Z{}) {}
};

// User
S<SomeClass, int> s;
s.foo(3.14);

您可以创建客户应该 define/specialize:

// In library
template <typename> struct DefaultType; // declaration without definition.

template<typename T>
struct S {
  template<typename X, typename Z = typename DefaultType<X>::type>
  void foo(X x, Z z = Z{}) {}
};


// In user code
template <typename> struct DefaultType
{
    using type = int;
};

S<SomeClass> s;
s.foo(3.14); // z == int(0)

如果您希望您的客户完全控制他们的类型,您可以设计库,使默认类型成为 class 模板的参数化 T 类型的一部分 S:

// In library
/// @attention `T` shall have a public alias declaration name `Default`
template<typename T>
struct S {
  template<typename X, typename Z = typename T::Default>
  void foo(X x, Z z = Z{}) {}
};

// In user code

// Default config for all my types: let my type inherit from this class.
struct DefaultConfig {
   using Default = int;
};

struct SomeClass : DefaultConfig {};

int main() {
    S<SomeClass> s;
    s.foo(3.14); // z == int(0)
};