gpt4 book ai didi

c++ - 在构造函数中使用通用引用时如何允许默认构造?

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:44:35 25 4
gpt4 key购买 nike

(注意:我找不到合适的标题)

我使用的是 Visual Studio 2013。我的项目中有以下代码:

template< class ConditionType >
class Not
{
ConditionType m_condition;
public:
using this_type = Not<ConditionType>;

template< class ...Args
, typename = std::enable_if<
!std::is_same< this_type, typename std::decay<Args>::type...>::value
>::type
>
Not( Args&&... args )
: m_condition( std::forward<Args>(args)... ) {}


Not( const Not& ) = default;
Not& operator=( const Not& ) = default;

template< class ...Args >
bool operator()( Args&&... args ) const
{
return ! m_condition( std::forward<Args>(args)... );
}

friend inline bool operator==( const Not& left, const Not& right )
{
return left.m_condition == right.m_condition;
}

friend inline bool operator<( const Not& left, const Not& right )
{
return left.m_condition < right.m_condition;
}

};

明显的目的是我有一个 ConditionType,它是一个可比较的函数对象,我想获得一个与其相反的类型。例如:

class KeyIsPressed
{
KeyId m_key;
public:
KeyIsPressed( KeyId key ) : m_key( std::move(key) ) {}

bool operator()( const InputStateBuffer& states ) const
{
return states.current().keyboard().is_key_pressed( m_key );
}
friend inline bool operator==( const KeyIsPressed& left, const KeyIsPressed& right )
{
return left.m_key == right.m_key;
}
friend inline bool operator<( const KeyIsPressed& left, const KeyIsPressed& right )
{
return left.m_key < right.m_key;
}
};

void somewhere( const InputStateBuffer& input_state_buffer )
{
Not<KeyIsPressed> condition { KEY_SHIFT };

if( condition( input_state_buffer ) )
do_something();
};

在我开始使用不需要任何构造函数参数的条件类型之前,这到目前为止效果很好。在这种情况下,visual studio 编译器会触发错误:

error C2512: 'blahblah::Not<blahblah::SomeConditionType>::Not' : no appropriate default constructor available

我试图通过添加一些条件或 Not 构造函数的特化来解决这个问题,但到目前为止没有任何效果。我看不到简单的解决方案,但我对 enable_if 和相关结构的了解有限。

问题的根源是我确实需要在 Not 构造函数中使用可变模板参数来将构造函数参数传递给实际条件。但是,当没有参数并且可以默认构造条件时,我的代码似乎无法生成空的可变参数模板;可能是因为 enable_if 生成了最后一个类型。我在构造函数中使用的 enable_if 是为了确保复制构造始终调用 Not 复制构造函数,而不是将 Not to copy 转发给条件构造函数。

我找不到的是如何在这种情况下允许 Not 中的默认构造。

编辑>

这是一个完整的重现案例:

#include <type_traits>

template< class ConditionType >
class Not
{
ConditionType m_condition;
public:
using this_type = Not<ConditionType>;

template< class ...Args
, typename = std::enable_if<
!std::is_same< this_type, typename std::decay<Args>::type...>::value
>::type
>
Not( Args&&... args )
: m_condition( std::forward<Args>(args)... ) {}


Not( const Not& ) = default;
Not& operator=( const Not& ) = default;

template< class ...Args >
bool operator()( Args&&... args ) const
{
return ! m_condition( std::forward<Args>(args)... );
}

friend inline bool operator==( const Not& left, const Not& right )
{
return left.m_condition == right.m_condition;
}

friend inline bool operator<( const Not& left, const Not& right )
{
return left.m_condition < right.m_condition;
}

};

class ConditionThatCompile
{
int m_key;
public:
ConditionThatCompile( int key ) : m_key( key ) {}

bool operator()( const int& value ) const
{
return m_key > value;
}
friend inline bool operator==( const ConditionThatCompile& left, const ConditionThatCompile& right )
{
return left.m_key == right.m_key;
}
friend inline bool operator<( const ConditionThatCompile& left, const ConditionThatCompile& right )
{
return left.m_key < right.m_key;
}
};

class ConditionThatDoNotCompile
{
public:
bool operator()( const int& value ) const
{
return true;
}
friend inline bool operator==( const ConditionThatDoNotCompile& left, const ConditionThatDoNotCompile& right )
{
return true;
}
friend inline bool operator<( const ConditionThatDoNotCompile& left, const ConditionThatDoNotCompile& right )
{
return false;
}
};

void do_something();

void somewhere()
{
Not<ConditionThatCompile> compiling_condition { 42 };

if( compiling_condition( 100 ) )
do_something();

Not<ConditionThatDoNotCompile> not_compiling_condition;
};

最佳答案

最简单的方法是派生并继承所有构造函数:

template<typename F>
struct Not : private F
{
using F::F;

template<typename... A>
bool operator()(A&&... a) const { return !F::operator()(std::forward<A>(a)...); }
};

如果您的编译器不支持继承基础构造函数,您确实需要定义一个构造函数模板,尽管我以前的理解是,这个模板似乎确实与隐式定义的复制/移动构造函数混淆了。这种情况下的解决方案是

template<typename F>
class Not : F
{
template<typename... A> struct ok : std::true_type {};
template<typename... A> struct ok<Not, A...> : std::false_type {};

public:
template<typename... A, typename = typename std::enable_if<
ok<typename std::decay<A>::type...>{}
>::type>
Not(A&&... a) : F{std::forward<A>(a)...} {}

template<typename... A>
bool operator()(A&&... a) const { return !F::operator()(std::forward<A>(a)...); }
};

这有点笨拙,但您对 std::is_same 的使用不正确。如果这对你有用,最好以更简洁的方式编写 ok,包括在类之外的 decay 以便更普遍地使用,并给它起一个更好的名字。这样就不会那么笨拙了。

A live example表明这两种选择在一些扩展测试中都有效。

关于c++ - 在构造函数中使用通用引用时如何允许默认构造?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23459432/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com