我的应用程序中存在一个问题,我想声明函数应用程序会被编译器拒绝。有没有办法用SFINAE检查这个?
例如,假设我要验证std::transform
到const
范围是非法的。这是我到目前为止所做的:
#include <algorithm>
#include <functional>
#include <iostream>
namespace ns
{
using std::transform;
template<typename Iterator1, typename Iterator2, typename UnaryFunction>
struct valid_transform
{
static Iterator1 first1, last1;
static Iterator2 first2;
static UnaryFunction f;
typedef Iterator2 yes_type;
typedef struct {yes_type array[2];} no_type;
static no_type transform(...);
static bool const value = sizeof(transform(first1, last1, first2, f)) == sizeof(yes_type);
};
}
int main()
{
typedef int *iter1;
typedef const int *iter2;
typedef std::negate<int> func;
std::cout << "valid transform compiles: " << ns::valid_transform<iter1,iter1,func>::value << std::endl;
std::cout << "invalid transform compiles: " << ns::valid_transform<iter1,iter2,func>::value << std::endl;
return 0;
}
不幸的是,我的特质拒绝了合法和非法案件。结果:
$ g++ valid_transform.cpp
$ ./a.out
valid transform compiles: 0
invalid transform compiles: 0
答案 0 :(得分:4)
您的问题与SFINAE + sizeof = detect if expression compiles类似。
该答案的 摘要:sizeof
评估传递给它的表达式的类型,包括实例化一个函数模板,但它不会生成函数调用。这就是Lol4t0观察sizeof(std::transform(iter1(), iter1(), iter2(), func()))
即使std::transform(iter1(), iter1(), iter2(), func())
没有编译的原因。
通过从Lol4t0的答案中评估要提供给std::transform
的任何输出范围的模板,可以解决具体问题。但是,在模板中验证函数调用将编译的一般问题似乎无法用sizeof + SFINAE
技巧解决。 (它需要一个可从运行时函数调用派生的编译时表达式。)
您可能想尝试ConceptGCC,看看是否允许您以更方便的方式表达必要的编译时检查。
答案 1 :(得分:3)
在我的回答中,我想关注问题,如何确定,如果给定迭代器常量:
提到了std::is_const
,但在这种情况下它对我来说不起作用(gcc 4.7)。
我认为,它的实施就像
template <typename T>
struct is_const
{
enum {value = false };
};
template <typename T>
struct is_const<const T>
{
enum {value = true };
};
现在,我们无法检查具有此结构的引用类型,它们与特化不匹配,因为const T
将匹配int& const
,即对int 的常量引用,而不是{ {1}},即对常量int 的引用,并且首先没有任何意义。
好的,但是我们能够确定迭代器是否与以下结构一致:
const int&