2010-09-21 4 views
0

Я хотел бы создать оболочку с одним присваиванием для базовых типов (например, int), которая говорит как int, идет как int, пахнет как int, но может быть только изменен или назначен не более одного раза (например, на некоторых чистых функциональных языках). Например (конструктор копирования опущен, чтобы простой пример):Одиночное назначение для базовых типов в C++

template<class T> 
struct SA { 
    SA<T>(T init) : wasAssigned(false) { 
     val = tmp = init; 
    } 
    SA<T> & operator=(const T& other) { 
     if (!wasAssigned) { 
      if (val != tmp) { 
       val = tmp; 
      } else { 
       val = tmp = other; 
      } 
      wasAssigned = true; 
     } 
     return *this; 
    } 
    operator T&() { 
     if (!wasAssigned && (val != tmp)) { 
      wasAssigned = true; 
      val = tmp; 
     } else { 
      tmp = val; 
     } 
     return tmp; 
    } 
private: 
    bool wasAssigned; 
    T val, tmp; 
}; 

Это близко, но не идеально. Он основан на тест равенства Val/TMP для обнаружения изменений, и не в этом случае:

SA<int> i(3); 
cin >> i; 
i = 5; 

Ифф в cin >> i присваивает такое же значение в качестве начального значения (3), я буду 5 в конце. Как это можно зафиксировать?

+0

Прошу прощения за вычеркивание очевидного вопроса, но я не могу остановить себя: зачем это нужно? – sbi

+0

Предположим, вы хотите, чтобы значение изменялось только первым вызовом RPC или позволяло пользователю изменять значение только в том случае, если оно не было заблокировано с помощью аргумента командной строки и т. Д. Очевидно, что есть способы сделать это без Single Назначение. Я хочу знать, может ли концепция быть обобщенной. –

ответ

2

Возможно, что-то вроде следующего может работать, хотя я не уверен на 100% о побочных эффектах. В основном возвращает ссылку на tmp на все, кроме первого вызова, который получает неконстантную ссылку, плюс const методы доступа только для чтения.

operator T&() { 
    if (wasAssigned) { 
    tmp = val; 
    return tmp; 
    } else { 
    wasAssigned = true; 
    return val; 
    } 
} 

operator const T&() const { 
    return val; 
} 

operator T() const { 
    return val; 
} 
+0

Где находится 'tmp'? – sbi

+0

'tmp' - это то же самое, что и в коде OP, член класса. – casablanca

+0

Это не сработает. Если вы передаете недавно созданный (но не назначенный) объект в cout, например, будет вызван «оператор T &», а поскольку wasAssigned установлен в true, вы будете зацикливаться на инициализированном значении. –

Смежные вопросы