是否可以为零模板参数进行模板特化?

Gil*_*tes 15 c++ c++17

假设我有一个这样的课程:

template <typename T>
struct S {
  int n = 1;
  S(T t) : n(t) {};
  S() = default;
};
Run Code Online (Sandbox Code Playgroud)

S如果我想使用这样的默认构造函数,是否可以更改某些内容以便可以在没有模板参数的情况下实例化S s {};

我想出的最好的办法是为模板参数分配一些虚假的默认值,使其成为可选的:

#include <iostream>

struct default_ {};

template <typename T = default_>
struct S {
  int n = 1;
  S(T t) : n(t) {};
  S() = default;
};


int main() {
  S<int> s1 {10};
  std::cout << "Value:\n" << s1.n << std::endl;
  S s2 {};
  std::cout << "Value:\n" << s2.n << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

https://repl.it/repls/RegalCoolDeal

H K*_*nan 13

如果T仅用于构造函数,则不需要对整个类进行模板化:

#include <iostream>

struct S {
  int n = 1;

  template <typename T>
  S(T t) : n(t) {};

  S() = default;
};

int main() {
  S s1 {10};
  std::cout << "Value:\n" << s1.n << std::endl;
  S s2 {};
  std::cout << "Value:\n" << s2.n << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

  • 这不允许编译行 ```S&lt;int&gt; s1 {10};```,该行位于原始问题中,也是要求恕我直言的一部分。 (2认同)
  • @Hack06。我在问题的任何地方都没有看到这个要求。 (2认同)

小智 9

您可以将 S 专门用于 void 并创建一个 CTAD https://en.cppreference.com/w/cpp/language/class_template_argument_deduction

#include <iostream>

template <typename T>
struct S {
  int n = 1;
  S(T t) : n(t) {}; // no default
};

template <>
struct S<void> {
  int n = 1;
  S() = default;  // only default
};

// CTAD calls to constructor S() will instantiate as S<void> 
template<typename... T> S() -> S<void>;   

int main() {
  S<int> s1 {10};
  std::cout << "Value:\n" << s1.n << std::endl;
  S s2 {};  // here CTAD will be trigged
  std::cout << "Value:\n" << s2.n << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

cppinsights 的链接可能有助于了解正在实例化的内容和位置:https ://cppinsights.io/s/8f0f4bf6

  • 谢谢!这对我来说似乎更好。请注意,CTAD 需要 C++17 才能编译。 (2认同)