gpt4 book ai didi

c++ - 我可以在控制流语句中使用 SFINAE 测试吗?

转载 作者:搜寻专家 更新时间:2023-10-31 01:59:02 24 4
gpt4 key购买 nike

我有一个 SFINAE 测试,用于检查类是否具有函数。测试工作正常,但当我尝试在 if 语句中使用它时出现编译器错误。

//SFINAE test for setInstanceKey()
template <typename K>
class HasSetInstanceKey
{
template <typename C>
static char test( typeof(&C::setInstanceKey) );

template <typename C>
static long test(...);

public:
enum { value = 1 == sizeof(test<K>(0)) };
};

我在第二行收到“错误:‘class Node’没有名为‘setInstanceKey’的成员”,尽管应该执行 else 子句。

if ( 0 != HasSetInstanceKey<T>::value)
instance->setInstanceKey(instanceKey);
else
...

有没有办法让它工作?

谢谢。

最佳答案

仅仅因为从未进入 if 分支并不意味着分支中的代码可能无效。 (另一种思考方式:您无法保证任何优化,但您的代码仅在死分支优化下有效。)

您所做的是将分支转移到一个函数。通常你有这样一个框架:

// holds some integral constant
template <typename T, T V>
struct integral_constant
{
static const T value = V;
};

// holds a boolean constant
template <bool V>
struct bool_type : integral_constant<bool, V>
{};

typedef bool_type<true> true_type; // a true boolean constant
typedef bool_type<false> false_type; // a false boolean constant

typedef const true_type& true_tag; // tag a function as the true variant
typedef const false_type& false_tag; // tag a function as the false variant

然后是这样的:

namespace detail
{
template <typename T, typename KeyType>
void foo(T* instance, const KeyType& instanceKey, true_tag)
{
// we are in the true variant, so our meta-function's value was true
// therefore, instance has the ability to do setInstanceKey
instance->setInstanceKey(instanceKey);
}

template <typename T, typename KeyType>
void foo(T*, const KeyType&, false_tag)
{
// we are in the false variant, so our meta-function's value was false
// therefore, instance does not have the right capabilities,
// so do nothing
}
}

// interface, forwards to correct implementation function
template <typename T, typename KeyType>
void foo(T* instance, const KeyType& instanceKey)
{
// pass instance, but to the overloaded foo
// that accepts the right boolean result
detail::foo(instance, instanceKey, // plug the value into a bool_type,
bool_type<HasSetInstanceKey<T>::value>()); // and instantiate it
// will either go into the true_tag or false_tag
}

为了便于使用,元函数必须继承自正确的 bool_type 是一种很好的做法:

namespace detail
{
// implementation
template <typename K>
class HasSetInstanceKey
{
// note, using char and long doesn't necessarily guarantee
// they each have a unique size. do this instead:
typedef char yes[1];
typedef char no[2]; // these must have different sizes

template <typename C>
static yes& test( typeof(&C::setInstanceKey) );

template <typename C>
static no& test(...);

public:
// check against size of yes result
static const bool value = sizeof(test<K>(0)) == sizeof(yes);
};
}

template <typename K>
struct HasSetInstanceKey : // delegate to implementation, take result and
bool_type<detail::HasSetInstanceKey<K>::value> // inherit from the
// appropriate bool_type
{};

所以它就变成了:

template <typename T, typename KeyType>
void foo(T* instance, const KeyType& instanceKey)
{
// because it inherits from bool_type, it can be implicitly
// converted into either true_tag or false_tag
detail::foo(instance, instanceKey, HasSetInstanceKey<T>());
}

关于c++ - 我可以在控制流语句中使用 SFINAE 测试吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3472620/

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