Çok fazla farklı cevabın olması beni şaşırtıyor, ancak neredeyse hepsi ağır şablon büyüsüne güveniyor. Şablonlar güçlüdür, ancak bazen makrolar kısaca onları yener. Maksimum çok yönlülük genellikle her ikisini birleştirerek elde edilir.
Bir makro yazdım FROM_CONST_OVERLOAD()
Const işlevini çağırmak için const işlevine yerleştirilemeyen .
Örnek kullanım:
class MyClass
{
private:
std::vector<std::string> data = {"str", "x"};
public:
// Works for references
const std::string& GetRef(std::size_t index) const
{
return data[index];
}
std::string& GetRef(std::size_t index)
{
return FROM_CONST_OVERLOAD( GetRef(index) );
}
// Works for pointers
const std::string* GetPtr(std::size_t index) const
{
return &data[index];
}
std::string* GetPtr(std::size_t index)
{
return FROM_CONST_OVERLOAD( GetPtr(index) );
}
};
Basit ve tekrar kullanılabilir uygulama:
template <typename T>
T& WithoutConst(const T& ref)
{
return const_cast<T&>(ref);
}
template <typename T>
T* WithoutConst(const T* ptr)
{
return const_cast<T*>(ptr);
}
template <typename T>
const T* WithConst(T* ptr)
{
return ptr;
}
#define FROM_CONST_OVERLOAD(FunctionCall) \
WithoutConst(WithConst(this)->FunctionCall)
Açıklama:
Birçok yanıtta da belirtildiği gibi, sabit olmayan bir üye işlevde kod yinelemesini önlemek için tipik desen şudur:
return const_cast<Result&>( static_cast<const MyClass*>(this)->Method(args) );
Bu kazan plakasının birçoğu tip çıkarımı kullanılarak önlenebilir. İlk olarak, argümanının türünü ihlal eden ve sabit niteleyiciyi kaldıran const_cast
kapsüllenebilir WithoutConst()
. İkincisi, benzer bir yaklaşım imlecin WithConst()
const-nitelendirilmesi için kullanılabilir this
, bu da const aşırı yüklenmiş yöntemi çağırmayı sağlar.
Geri kalanı, çağrıyı doğru şekilde nitelendiren this->
ve sonucun sabitini kaldıran basit bir makrodur . Makroda kullanılan ifade neredeyse her zaman 1: 1 iletilen argümanlarla basit bir işlev çağrısı olduğundan, çoklu değerlendirme gibi makroların dezavantajları devreye girmez. Üç nokta ve__VA_ARGS__
ayrıca kullanılabilir, ancak virgül (çünkü bağımsız değişken ayırıcılar) parantez içinde gerçekleşir.
Bu yaklaşımın çeşitli faydaları vardır:
- Minimal ve doğal sözdizimi - sadece aramayı sarın
FROM_CONST_OVERLOAD( )
- Ek üye işlevi gerekmez
- C ++ 98 ile uyumlu
- Basit uygulama, şablon meta programlaması ve sıfır bağımlılık yok
- Genişletilebilir: Diğer const ilişkiler (gibi eklenebilir
const_iterator
, std::shared_ptr<const T>
vs.). Bunun WithoutConst()
için, karşılık gelen tipler için aşırı yükleme yapın .
Sınırlamalar: bu çözüm sabit olmayan aşırı yüklenmenin sabit aşırı yüklemeyle tamamen aynı olduğu senaryolar için optimize edilmiştir, böylece argümanlar 1: 1 iletilebilir. Mantık farklıysa ve const sürümünü üzerinden çağırmıyorsanız, this->Method(args)
diğer yaklaşımları düşünebilirsiniz.