我想进入更多的模板元编程.我知道SFINAE代表"替换失败不是错误".但是有人能告诉我SFINAE的用处吗?
我刚刚发现了如何检查是否operator<<
提供了类型.
template<class T> T& lvalue_of_type();
template<class T> T rvalue_of_type();
template<class T>
struct is_printable
{
template<class U> static char test(char(*)[sizeof(
lvalue_of_type<std::ostream>() << rvalue_of_type<U>()
)]);
template<class U> static long test(...);
enum { value = 1 == sizeof test<T>(0) };
typedef boost::integral_constant<bool, value> type;
};
Run Code Online (Sandbox Code Playgroud)
这个技巧是众所周知的,还是我刚刚获得了诺贝尔奖的元编程?;)
编辑:我使代码更容易理解,更容易适应两个全局函数模板声明lvalue_of_type
和rvalue_of_type
.
我在一个std::optional
实现中遇到了这个代码:
template <class T, class U>
struct is_assignable
{
template <class X, class Y>
constexpr static bool has_assign(...) { return false; }
template <class X, class Y, size_t S = sizeof((std::declval<X>() = std::declval<Y>(), true)) >
// the comma operator is necessary for the cases where operator= returns void
constexpr static bool has_assign(bool) { return true; }
constexpr static bool value = has_assign<T, U>(true);
};
Run Code Online (Sandbox Code Playgroud)
我无法理解它是如何工作或如何评估的部分是size_t S = sizeof((std::declval<X>() = std::declval<Y>(), true))
我知道如果赋值操作失败,它将回退到返回false的has_assign的第一个定义,但我不知道为什么它有该, true)
部分.
我使用在assign操作符上返回void的结构进行了一些测试,并删除了, …
我需要实现算法,使用模板递归计算两个向量的标量积.
有我的代码:
#include <iostream>
#include <vector>
template<typename T, int Size>
T scalar_product(const std::vector<T> &a, const std::vector<T> &b)
{
return a[Size - 1]*b[Size - 1] + (scalar_product<T, Size - 1>(a, b));
}
template<typename T>
T scalar_product<T, 0>(const std::vector<T> &a, const std::vector<T> &b) // error!
{
return a[0] * b[0];
}
int main()
{
std::vector<int> a(3, 1);
std::vector<int> b(3, 3);
std::cout << scalar_product<int, 3>(a, b);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果我使用这种专业化T scalar_product<T, 0>(...)
,我会收到错误" 'scalar_product':非法使用显式模板参数 ".但是,如果我像这个T scalar_product(...)
编译器报告一样删除它,递归将是无限的(因为没有专业化,据我所知).
这里有很多这类问题,但我找不到有用的答案.如何在不使用类的情况下专门化这个功能?先谢谢你了!
基类是:
#include <memory>
namespace cb{
template< typename R, typename ... Args >
class CallbackBase
{
public:
typedef std::shared_ptr< CallbackBase< R, Args... > >
CallbackPtr;
virtual ~CallbackBase()
{
}
virtual R Call( Args ... args) = 0;
};
} // namespace cb
Run Code Online (Sandbox Code Playgroud)
派生类是这样的:
namespace cb{
template< typename R, typename ... Args >
class FunctionCallback : public CallbackBase< R, Args... >
{
public:
typedef R (*funccb)(Args...);
FunctionCallback( funccb cb_ ) :
CallbackBase< R, Args... >(),
cb( cb_ )
{
}
virtual ~FunctionCallback() …
Run Code Online (Sandbox Code Playgroud)