Arg türlerini ayırt etmek için BOOST_STRONG_TYPEDEF kullanmak, ancak segment hatasına neden olmak
Aynı enum türünde birkaç değişken gerektiren bir yöntemim var. Derleyicinin kullandığım yanlış argümanı geçip geçmediğimi algılamasına izin vermek için BOOST_STRONG_TYPEDEF
. Ancak, bir örnek oluşturduğumda ve bir IF ifadesi içinde karşılaştırdığımda bir segment hatası alıyorum.
Boost sürümü 1.74'tür
enum class Testable
{
UNDEFINED,
A,
B
};
BOOST_STRONG_TYPEDEF(Testable, SomeType)
int main()
{
SomeType abc{Testable::UNDEFINED};
std::cout << "START" << std::endl;
if(abc == Testable::UNDEFINED) // Seg faults here
{
volatile int j = 0;
}
std::cout << "FINISH" << std::endl;
}
GDB geri izleme, bunun bir yığın taşması / özyinelemeli çağrı olduğunu öne sürüyor:
#1 0x00007ffff74c5d9d in boost::operators_impl::operator== (y=@0x7fffffcc9e44:
#2 0x00007ffff74c5d9d in boost::operators_impl::operator== (y=@0x7fffffcc9e44:
#3 0x00007ffff74c5d9d in boost::operators_impl::operator== (y=@0x7fffffcc9e44:
#4 0x00007ffff74c5d9d in boost::operators_impl::operator== (y=@0x7fffffcc9e44:
#5 0x00007ffff74c5d9d in boost::operators_impl::operator== (y=@0x7fffffcc9e44:
#6 0x00007ffff74c5d9d in boost::operators_impl::operator== (y=@0x7fffffcc9e44:
İçin çok fazla belge yok BOOST_STRONG_TYPEDEF
. Yanlış mı kullanıyorum?
Boost sürümü 1.74'tür. Clang kullanıyorum.
Yanıtlar
Dezenfektan diyor
==3044==ERROR: AddressSanitizer: stack-overflow on address 0x7ffcc58b3ff8 (pc 0x56310c340e84 bp 0x7ffcc58b4000 sp 0x7ffcc58b3ff
0 T0)
#0 0x56310c340e84 in boost::operators_impl::operator==(Testable const&, SomeType const&) /home/sehe/custom/boost_1_75_0/boo
Sorun, Boost'un STRONG_TYPEDEF'in türev türünü temel türle tamamen sıralı hale getirmesidir:
struct SomeType
: boost::totally_ordered1<SomeType, boost::totally_ordered2<SomeType, Testable>>
{
Testable t;
explicit SomeType(const Testable& t_) noexcept((boost::has_nothrow_copy_constructor<Testable>::value)) : t(t_) {}
SomeType() noexcept( (boost::has_nothrow_default_constructor<Testable>::value)) : t() {}
SomeType(const SomeType& t_) noexcept( (boost::has_nothrow_copy_constructor<Testable>::value)) : t(t_.t) {}
SomeType& operator=(const SomeType& rhs) noexcept((boost::has_nothrow_assign<Testable>::value)) {
t = rhs.t;
return *this;
}
SomeType& operator=(const Testable& rhs) noexcept((boost::has_nothrow_assign<Testable>::value)) {
t = rhs;
return *this;
}
operator const Testable&() const { return t; }
operator Testable&() { return t; }
bool operator==(const SomeType& rhs) const { return t == rhs.t; }
bool operator<(const SomeType& rhs) const { return t < rhs.t; }
};
Bu örtük dönüştürme kaynağını kaldırırsanız:
struct SomeType
: boost::totally_ordered1<SomeType
/*, boost::totally_ordered2<SomeType, Testable>*/>
{
// ...
bu JustWorks (TM). Dönüşüm operatörlerini explicit
de yapmanız gerektiğini ve her zaman dökümleri yapmanız gerektiğini iddia ediyorum :
Coliru'da Canlı
#include <boost/serialization/strong_typedef.hpp>
#include <iostream>
enum class Testable { UNDEFINED, A, B };
struct SomeType
: boost::totally_ordered1<SomeType
/*, boost::totally_ordered2<SomeType, Testable>*/>
{
Testable t;
explicit SomeType(const Testable& t_) noexcept((boost::has_nothrow_copy_constructor<Testable>::value)) : t(t_) {}
SomeType() noexcept( (boost::has_nothrow_default_constructor<Testable>::value)) : t() {}
SomeType(const SomeType& t_) noexcept( (boost::has_nothrow_copy_constructor<Testable>::value)) : t(t_.t) {}
SomeType& operator=(const SomeType& rhs) noexcept((boost::has_nothrow_assign<Testable>::value)) {
t = rhs.t;
return *this;
}
SomeType& operator=(const Testable& rhs) noexcept((boost::has_nothrow_assign<Testable>::value)) {
t = rhs;
return *this;
}
explicit operator const Testable&() const { return t; }
explicit operator Testable&() { return t; }
bool operator==(const SomeType& rhs) const { return t == rhs.t; }
bool operator<(const SomeType& rhs) const { return t < rhs.t; }
};
int main() {
SomeType abc{ Testable::UNDEFINED };
std::cout << "START" << std::endl;
if (abc == SomeType{Testable::UNDEFINED}) {
volatile int j = 0;
}
std::cout << "FINISH" << std::endl;
}