kolay çözüm yaklaşık const_cast
unutup sadece açıkça hem aşırı yükleri uygulamaktır. Bu, standart kitaplık uygulamalarının yaptığı şeydir.
Örneğin, std::vector
operator[]
bir const
olan ve olmayan const
sürümü vardır. Hem VC++ hem de GCC, bu işleç için yinelenen uygulamalara sahiptir (sırasıyla, include/vector
veya stl_vector.h
dosyaları); Bu davranışı çoğaltmak için hiçbir const_cast
püf noktasını kullanır. senin findObject
uygulaması çok büyük ve karmaşık ise
Şimdi, o zaman ilk tercihi daha basit hale getirmek olmalıdır. Geçici bir çözüm olarak, bağımsız bir decltype
son geri dönüş türünü kullanarak iç (özel veya başka erişilemeyen) şablon işlevi açısından her iki aşırı yüklenmeyi de uygulayarak, doğru const
veya const
dönüş türünü argüman aracılığıyla alın. (typeid
uygulamanıza ürettiği isimlerin ne tür bağlı)
#include <iostream>
#include <vector>
#include <typeinfo> // just to demonstrate what's going on
// simple example data structure:
struct MyObject {};
struct MyList
{
MyObject elements[3] = { MyObject {}, MyObject {}, MyObject {} };
};
namespace internal
{
// &list.elements[0] will be either MyObject const* or MyObject*
template <class ConstOrNonConstList>
auto doFindObject(ConstOrNonConstList& list) -> std::vector<decltype(&list.elements[0])>
{
// let's say there was an immensely complicated function here,
// with a lot of error potential and maintenance nightmares
// lurking behind a simple copy & paste solution...
// just to demonstrate what's going:
std::cout << typeid(decltype(&list.elements[0])).name() << "\n";
std::vector<decltype(&list.elements[0])> result;
for (auto&& element : list.elements)
{
result.push_back(&element);
}
return result;
}
}
std::vector<const MyObject*> findObject(const MyList& list)
{
std::cout << "const version\n";
return internal::doFindObject(list);
}
std::vector<MyObject*> findObject(MyList& list)
{
std::cout << "non-const version\n";
return internal::doFindObject(list);
}
int main()
{
MyList list1;
MyList const list2;
auto obj1 = findObject(list1);
auto obj2 = findObject(list2);
}
Örnek çıktı:
non-const version
struct MyObject *
const version
struct MyObject const *
Ama açıkçası, bunu olmaz Burada basit bir örnektir. Fazla tasarlanmış görünüyor ve belki de biraz fazla zeki. Aşırı zeki kod nadiren iyi bir fikir, çünkü insanları karıştırıyor.
const_cast (liste) 'nin anlamı nedir? –
SergeyA
Argümanlardaki" const "belirteci, arayanın, kendisine iletilen verileri değiştirmeyeceği konusunda bir garantidir. Girilmesi gereken verilerin bir şartı değildir. Non-const verilerinde geçiş yapabilirsiniz. Yani const_cast (list) 'in anlamsız. Ayrıca, findObject() 'dan' const MyObject * 'döndürme de anlamsızdır. Nedenini anlamak için, bu snippet'i düşünün: const int C = 42; int i = C; –
düzgün yazarak bu çocukça const_cast fikirlerinden sessizce uzaklaşın. Güvenlik silahlarını neden silahlara koyduğunu biliyorsun, değil mi? –