繁体   English   中英

std :: is_base_of和if错误

[英]std::is_base_of and error with if

我的模板有问题:

我有两个构造函数和方法:.cpp:

Cell::Cell(sf::Vector2i& uPos, sf::Vector2f& cellDimensions, std::string& stateName)
    :unitPosition(uPos)
{
    setBasicParameters<std::string>(stateName,cellDimensions,uPos);
}

Cell::Cell(sf::Vector2i & uPos, sf::Vector2f & cellDimensions, int stateNumber)
    :unitPosition(uPos)
{
    setBasicParameters<int>(stateNumber,cellDimensions,uPos);
}

.hpp ::

//Basic parameters which are being used by constructors
    template < typename T = typename std::enable_if< std::is_base_of<int, T>::value, T>::type || typename std::enable_if< std::is_base_of<std::string, T>::value, T>::type>
    void setBasicParameters(T& object, sf::Vector2f& cellDimensions, sf::Vector2i& uPos);

template<typename T>
inline void Cell::setBasicParameters(T& object, sf::Vector2f& cellDimensions, sf::Vector2i& uPos)
{
    shape.setSize(cellDimensions);
    shape.setOutlineThickness(cellDimensions.x / 10.0f); //10%

    shape.setOutlineColor(constants::cell::FILL_COLOR);

    shape.setPosition(uPos.x*cellDimensions.x, uPos.y*cellDimensions.y);

    if (!StateSystem::isStateExist(object))
    {
        Logger::Log(constants::error::stateSystem::STATE_DOES_NOT_EXIST, Logger::STREAM::BOTH, Logger::TYPE::ERROR);
        state = StateSystem::getNumberOfState(constants::defaults::EMPTY);
    }
    else
    {
        if (std::is_base_of<std::string, T>::value)
            state = StateSystem::getNumberOfState(object);  
        else state = object;

        setColor(StateSystem::getColorOfState(state));
    }
}

和问题在那里:

if (std::is_base_of<std::string, T>::value)
            state = StateSystem::getNumberOfState(object);  
        else state = object;

在这种情况下,我检查T的类型,如果它是std :: string,则使用StateSystem中的方法,该方法将名称更改为数字。 换句话说,如果T为int,则无需更改它,因此我可以立即将T分配给state(state为int)。 但是我的编译器检查dwo选项并给我错误:

Severity    Code    Description Project File    Line    Suppression State

错误C2440'=':无法从'std :: string'转换为'uint8_t'

Severity    Code    Description Project File    Line    Suppression State
Error   C2664   'int8_t mv::StateSystem::getNumberOfState(std::string)': cannot convert argument 1 from 'int' to 'std::string'  

如果没有两种不同的方法,我可以修理它吗?

问题是这里的if语句...

if (std::is_base_of<std::string, T>::value)

...是运行时分支 即使可以在编译时评估is_base_of ,编译器仍被迫编译if语句的两个分支,即使它们的正确性取决于is_base_of条件。


如果没有两种不同的方法,我可以修理它吗?

C ++ 17引入了if constexpr (...) ,它在编译时进行分支。 这仍然要求两个分支都是可解析的,但仅实例化与谓词匹配的分支。 因此,未采用的分支可能是“无效的”,您的程序将按预期运行。

if constexpr (std::is_base_of<std::string, T>::value)
    state = StateSystem::getNumberOfState(object);  
else state = object;

如果您无权使用C ++ 14,并且确实不想使用两个不同的函数,则可以实现与if constexpr(...)等效的构造。 该实施需要大量的样板。 最终结果将如下所示:

static_if(std::is_base_of<std::string, T>{})
    .then([&](auto){ state = StateSystem::getNumberOfState(object); })
    .else_([&](auto){ state = object; })(_);

我在CppCon 2016Meeting C ++ 2016上做了一个名为“在C ++ 14中实现static控制流”的 static_if ,它解释了static_if工作方式以及如何自己实现它。


如果您决定使用两个不同的功能是可以接受的,则可以通过以下方法解决此问题:

if (!StateSystem::isStateExist(object))
{
    // ...as before...
}
else
{
    dispatch(state, std::is_base_of<std::string, T>{});
    // ...as before...
}

其中dispatch定义为:

void dispatch(State& state, Object& object, std::true_type)
{
    state = StateSystem::getNumberOfState(object);
}

void dispatch(State& state, Object& object, std::false_type)
{
    state = object;
}

std::is_base_of是编译时的东西。 例如,您应该将它与static_assert一起使用。 在C ++中,运行时的类型信息比较复杂,您应该使用RTTI或dynamic_cast的东西。

该答案给出了有关差异的答案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM