簡體   English   中英

使用std :: enable_if時的對象切片

[英]Object slicing when using std::enable_if

我試圖使用std::enable_if來專門化一個類,如果它的一個子類具有定義的特定成員函數。 否則,它應該使用在基類中定義的默認實現。

#include <boost/mpl/list.hpp>
#include <boost/function_types/function_type.hpp>
#include <boost/tti/has_member_function.hpp>

#include <iostream>
#include <type_traits>
#include <memory>

BOOST_TTI_HAS_MEMBER_FUNCTION(f2)

class Base
{
public:
    virtual double f1(double x, double y) const
    {
        std::cout << "Called Base Method" << std::endl;
        return 0.0;
    }
};

template<typename Derived>
class A : public Base
{
public:
    template<typename T = Derived>
    typename std::enable_if
              < has_member_function_f2< T
                                      , double
                                      , boost::mpl::list<double>
                                      , boost::function_types::const_qualified
                                      >::value
              , double
              >::type
    f1(double x, double y) const
    {
        std::cout << "Called Derived Method" << std::endl;
        return static_cast<const Derived* const>(this)->f2(x);
    }
};


class B : public A<B>
{
public:
    double f2(double x) const
    {
        return 1.0;
    }
};

int main()
{
    std::unique_ptr<Base> base_instance( new B );
    std::cout << base_instance->f1(100.0, 10.0) << std::endl;

    B b_instance;
    std::cout << b_instance.f1(100.0, 10.0) << std::endl;

    return 0;
}

我原以為要印刷

Called Derived Method
1
Called Derived Method
1

但是相反,我得到了

Called Base Method
0
Called Derived Method
1

所以它看起來像正在發生一些物體切片。 我不能為我的生活看到為什么會出現這種情況,如果有人能幫助我,我將不勝感激。

如果它以任何方式幫助這是用g ++ 4.7.2編譯的

模板功能不能是虛擬的。 這也意味着模板函數永遠不會覆蓋基類中的虛函數,即使它的特定實例化簽名恰好匹配。

為了達到你想要的效果,你需要將A作為一個整體來專門化,以便在一個版本中提供成員而在另一個版本中不提供。

@ Sebastian的回答解釋了這個問題,但是建議的解決方案會有問題:你不能使用CRTP專門化派生類的屬性上的基類模板,因為在實例化基類時派生類是不完整的。 我建議你改為總是覆蓋A f1 ,並使用標簽調度來確定是派生到派生類中的f2還是派生到Base的默認實現:

template<typename Derived>
class A : public Base
{
    double f1_impl(boost::mpl::true_, double x, double) const
    {
        std::cout << "Called Derived Method\n";
        return static_cast<const Derived*>(this)->f2(x);
    }
    double f1_impl(boost::mpl::false_, double x, double y) const
    {
        return Base::f1(x, y);
    }

public:
    double f1(double x, double y) const override
    {
        using has_f2 = typename has_member_function_f2
            < Derived
            , double
            , boost::mpl::list<double>
            , boost::function_types::const_qualified
            >::type;
        return f1_impl(has_f2{}, x, y);
    }
};

DEMO

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM