我正在写一个我想保留标题的库。在代码中我有这样的东西:
// Wrapper.h
#ifndef INCLUDED_WRAPPER_H
#define INCLUDED_WRAPPER_H
namespace quux {
template <typename T, typename U>
class Wrapper
{
T m_t;
U m_u;
public:
Wrapper(T const & t, U const & u) : m_t(t), m_u(u) { }
// ...
};
} // namespace quux
#endif // INCLUDED_WRAPPER_H
// Foo.h
#ifndef INCLUDED_FOO_H
#define INCLUDED_FOO_H
#include <type_traits>
#include "Wrapper.h"
namespace quux {
// if some type is special, then there will be a specialization of this
// struct derived from std::true_type
template <typename T> struct is_special : std::false_type { };
class Foo
{
template <typename T>
Wrapper<Foo, T> impl(T const & t, std::true_type ) const
{
return Wrapper<Foo, T>(*this, t);
}
template <typename T>
T const & impl(T const & t, std::false_type ) const;
{
return t;
}
public:
template <typename T>
auto operator()(T const & t) const // using automatic return type deduction
{
return impl(t, is_special<T>());
}
};
#if 1
Foo const foo;
#else
template <typename T>
auto foo(T const & t) // using automatic return type deduction
{
return Foo()(t);
}
#endif
} // namespace quux
#endif // INCLUDED_FOO_H
我看到两种不同的方法来拥有一个名为“quux :: foo”的可调用实体:一个名为foo的常量对象(#if 1 - branch)或一个名为foo的函数,它将其参数转发给一个Foo对象(#else-branch)。我更喜欢哪个版本? const对象具有内部链接,因此如果标头包含在多个转换单元中,则不会出现链接器错误。这两种方法之间是否存在显着差异?
答案 0 :(得分:0)
在调用函数时,函数对象没有状态,我会使用函数接口。
首先,因为函数可以重载,而函数对象不能在函数对象的主体之外。您可能希望为您的功能启用ADL扩展。
其次,因为函数对象很奇怪。例如,它们无法转换为函数指针(在您的情况下没有充分理由)(注意您可以使用更多样板来修复它)。当简单的解决方案不足时,奇怪的解决方案只是一个好主意:在这种情况下,简单的完美转发功能更简单。
最后,您可能希望使您的函数完美前进,并让T&&
rvalues在最外层的API级别提供返回T
的函数。这使得临时工具的寿命延长能够通过你的功能。