Можно ли сделать специализацию шаблона для нулевых аргументов шаблона? - PullRequest
15 голосов
/ 11 июля 2020

Предположим, у меня есть такой класс:

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

Можно ли что-то изменить, чтобы можно было создать экземпляр 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;
}

https://repl.it/repls/RegalCoolDeal

Ответы [ 2 ]

13 голосов
/ 11 июля 2020

Если 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;
}
9 голосов
/ 11 июля 2020

Вы можете специализировать 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;
}

Ссылка на cppinsights может помочь понять, что и где создается: https://cppinsights.io/s/8f0f4bf6

...