Если вы не возражаете против Foo b = nullptr;
работающих, это довольно легко взломать. Имейте явный конструктор от int
и неявный от std::nullptr_t
.
Если вы не против работать, я не уверен, что это возможно. Единственный способ отличить литерал 0
и другие целочисленные литералы - это неявное преобразование первого в указатели и nullptr_t
. Таким образом, nullptr
предпочтет параметр nullptr_t
параметру указателя, поэтому, имея оба конструктора, вы можете отфильтровать аргументы nullptr
. Однако переходы 0
на указатели и nullptr_t
имеют одинаковый ранг, поэтому это может привести к уклонению аргументов 0
с двусмысленностью.
Хм ... что-то подобное может работать:
class Foo {
struct dummy;
public:
explicit Foo(int); // the version that allows Foo x(1);
Foo(dummy*); // the version that allows Foo x = 0;
template <typename T,
typename = typename std::enable_if<
std::is_same<T, std::nullptr_t>::value>::type>
Foo(T) = delete; // the version that prevents Foo x = nullptr;
};
Я на самом деле не пробовал. Теоретически шаблон должен участвовать только в разрешении перегрузки, когда аргумент равен nullptr
, поскольку в противном случае SFINAE убивает его. В этом случае, однако, он должен быть лучше конструктора указателя.
Как насчет 'Foo e (1);'? Как это справедливо? –
@LuchianGrigore: Являются ли они семантически идентичными? Если это так, я думаю, я могу объявить это недействительным. – Eric
Может быть, вы можете попробовать с конструктором, принимающим 'std :: nullptr_t' (просто идея ...) –