gpt4 book ai didi

c++ - enable_if 模板特化自定义特征

转载 作者:行者123 更新时间:2023-11-30 02:36:08 27 4
gpt4 key购买 nike

我试图了解 std::enable_if 是如何工作的 inn 模板参数。

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

using namespace std;


class Interface {};
class Value {};


class Stream
{
public:

template<typename T,
typename enable_if<
is_base_of< Interface, T>{}
>::type* = nullptr>
void
write(const shared_ptr<T>& v)
{
cerr << "Writing interface class" << endl;
}

template<typename T,
typename enable_if<
is_base_of< Value, T>{}
>::type* = nullptr>
void
write(const shared_ptr<T>& v)
{
cerr << "Writing value class" << endl;
}
};

class UserI : public Interface{};
class User : public Value{};

int main(int, char**)
{

auto interface = make_shared<UserI>();
auto value = make_shared<User>();

Stream s;
s.write(interface);
s.write(value);

return 0;
}

他们我试图通过提供自定义特征来检查对象是接口(interface)还是值实例来简化代码。

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

using namespace std;


class Interface {};
class Value {};

template<typename T>
struct is_interface
{
const static bool value = is_base_of< Interface, T>::value;
};

template<typename T>
struct is_value
{
const static bool value = is_base_of< Value, T>::value;
};

class Stream
{
public:

template<typename T,
typename enable_if<
is_interface<T>{}
>::type* = nullptr>
void
write(const shared_ptr<T>& v)
{
cerr << "Writing interface class" << endl;
}

template<typename T,
typename enable_if<
is_value<T>{}
>::type* = nullptr>
void
write(const shared_ptr<T>& v)
{
cerr << "Writing value class" << endl;
}
};

class UserI : public Interface{};
class User : public Value{};

int main(int, char**)
{

auto interface = make_shared<UserI>();
auto value = make_shared<User>();

Stream s;
s.write(interface);
s.write(value);

return 0;
}

但是第二个版本编译失败,出现以下错误:

test_t2.cc: In function ‘int main(int, char**)’:
test_t2.cc:58:26: error: no matching function for call to ‘Stream::write(std::shared_ptr<UserI>&)’
s.write(interface);
^
test_t2.cc:58:26: note: candidates are:
test_t2.cc:32:9: note: template<class T, typename std::enable_if<is_interface<T>{}>::type* <anonymous> > void Stream::write(const std::shared_ptr<_Tp1>&)
write(const shared_ptr<T>& v)
^
test_t2.cc:32:9: note: template argument deduction/substitution failed:
test_t2.cc:30:28: error: could not convert template argument ‘is_interface<UserI>{}’ to ‘bool’
>::type* = nullptr>

谁能解释一下第二个版本的问题是什么?

最佳答案

typename enable_if<
is_base_of< Interface, T>{}
>::type* = nullptr

之所以可行,是因为 std::is_base_of提供 operator bool将其实例隐式转换为 bool .你的特征没有提供,所以使用 is_interface<T>{}作为bool无效。

你可以写成operator bool为你的特质,但简单的解决方法就是使用 ::value相反:

template<typename T,
typename enable_if<
is_interface<T>::value //here
>::type* = nullptr>
void
write(const shared_ptr<T>& v)

就我个人而言,我认为在您的情况下,标签分派(dispatch)方法会更清晰且更易于维护。这是一个可能的实现:

class Stream
{
private:
struct interface_tag{};
struct value_tag{};
//if you ever need more tags, add them here
struct invalid_tag{};

template <typename T>
struct get_tag {
static interface_tag tagger (Interface*);
static value_tag tagger (Value*);
//add any mappings for other tags
static invalid_tag tagger (...);

using tag = decltype(tagger(std::declval<T*>()));
};

//convenience alias
template <typename T> using tag_t = typename get_tag<T>::tag;

public:
//clean public interface
template <typename T>
void write (const shared_ptr<T>& v) {
write(v, tag_t<T>{});
}

private:
//no more horrible std::enable_if
template<typename T>
void
write(const shared_ptr<T>& v, interface_tag)
{
cerr << "Writing interface class" << endl;
}

template<typename T>
void
write(const shared_ptr<T>& v, value_tag)
{
cerr << "Writing value class" << endl;
}
};

Live Demo

如果您需要有关此方法的任何说明,请询问。

关于c++ - enable_if 模板特化自定义特征,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33083011/

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