Ho una classe in cui desidero abilitare gli operatori di assegnazione copia/spostamento solo se un parametro di tipo per la classe è rispettivamente copia/sposta costruttibili. Così ho prova questo:enable_if con operatore di assegnazione copia/spostamento
#include <type_traits>
template<typename T>
struct Foobar {
Foobar(T value) : x(value) {}
Foobar(const Foobar &other) : x(other.x) {}
Foobar(Foobar &&other) : x(std::move(other.x)) {}
template<bool Condition = std::is_nothrow_copy_constructible<T>::value,
typename = typename std::enable_if<Condition>::type>
Foobar &operator=(const Foobar &rhs) {
x = rhs.x;
return *this;
}
template<bool Condition = std::is_nothrow_move_constructible<T>::value,
typename = typename std::enable_if<Condition>::type>
Foobar &operator=(Foobar &&rhs) {
x = std::move(rhs.x);
return *this;
}
T x;
};
int main() {
Foobar<int> foo(10);
Foobar<int> bar(20);
foo = bar;
foo.operator=(bar);
return 0;
}
Ora, Clang mi dà il seguente errore:
enable_if_test.cpp:31:9: error: object of type 'Foobar<int>' cannot be assigned because its copy assignment operator is implicitly
deleted
foo = bar;
^
enable_if_test.cpp:8:5: note: copy assignment operator is implicitly deleted because 'Foobar<int>' has a user-declared move
constructor
Foobar(Foobar &&other) : x(std::move(other.x)) {}
^
enable_if_test.cpp:32:9: error: call to deleted member function 'operator='
foo.operator=(bar);
~~~~^~~~~~~~~
enable_if_test.cpp:4:8: note: candidate function (the implicit copy assignment operator) has been implicitly deleted
struct Foobar {
^
enable_if_test.cpp:12:13: note: candidate function [with Condition = true, $1 = void]
Foobar &operator=(const Foobar &rhs) {
^
enable_if_test.cpp:19:13: note: candidate function [with Condition = true, $1 = void] not viable: no known conversion from
'Foobar<int>' to 'Foobar<int> &&' for 1st argument
Foobar &operator=(Foobar &&rhs) {
^
2 errors generated.
Ora, ho inserito il richiamo esplicito alla operatore di assegnazione per mostrare la stranezza dell'errore. Dice solo che il mio modello è una funzione candidata e non fornisce motivi per cui non è stato scelto.
La mia ipotesi è che poiché ho definito un costruttore di spostamenti, il compilatore ha implicitamente eliminato l'operatore di assegnazione delle copie. Poiché è implicitamente cancellato, non vuole neanche istanziare alcun modello. Perché si comporta in questo modo non lo so, comunque.
Come posso ottenere questo comportamento?
(Nota: il codice vero e proprio ha motivi legittimi per definire ciascuno dei membri, mi rendo conto che è inutile qui.)
T non è nel contesto immediato dell'operatore di assegnazione, in modo da SFINAE non può verificarsi. Se si aggiunge un parametro del modello fittizio predefinito a T, quindi sostituire T con tale parametro per il resto degli argomenti del modello, dovrebbe funzionare. – 0x499602D2
@ 0x499602D2 Non riesco a deludere la tua argomentazione. Per quanto ne so, il problema nell'OP è che i modelli di funzione non sono considerati come funzioni membro speciali (ad eccezione del ctor predefinito). – dyp
* "non vuole neanche istanziare alcun modello" * Per quello che ne so, si finirà con un operatore 'cancellato = (Foo const &)' e un operatore di specializzazione del modello di funzione = (Foo const &) ' . E come ultima risorsa, le funzioni non template sono preferite rispetto alle specializzazioni dei modelli di funzione: questo seleziona l'operatore cancellato. –
dyp