Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在编译时检查表达式是否非法?_C++_Sfinae_Typetraits_C++ Concepts - Fatal编程技术网

C++ 如何在编译时检查表达式是否非法?

C++ 如何在编译时检查表达式是否非法?,c++,sfinae,typetraits,c++-concepts,C++,Sfinae,Typetraits,C++ Concepts,我的应用程序中有一个问题,我想断言函数应用程序将被编译器拒绝。有没有办法和SFINAE核实一下 例如,假设我想验证std::transform到const范围是非法的。以下是我目前掌握的情况: #include <algorithm> #include <functional> #include <iostream> namespace ns { using std::transform; template<typename Iterator1,

我的应用程序中有一个问题,我想断言函数应用程序将被编译器拒绝。有没有办法和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;
}

你的问题类似于

该答案的摘要:
sizeof
计算传递给它的表达式的类型,包括实例化函数模板,但它不生成函数调用。这就是Lol4t0观察到的
sizeof(std::transform(iter1(),iter1(),iter2(),func())
编译的原因,即使
std::transform(iter1(),iter1(),iter2(),func())
没有编译

您的具体问题可以通过评估Lol4t0答案中的模板来解决,该模板用于提供给
std::transform
的任何输出范围。然而,使用
sizeof+SFINAE
技巧似乎无法解决在模板中验证函数调用将编译的一般问题。(它需要一个可从运行时函数调用派生的编译时表达式)


您可能想看看这是否允许您以一种更方便的方式表达必要的编译时检查。

在我的回答中,我想重点讨论一个问题,如果给定迭代器常数,如何确定: 提到了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 };

};

constepr
可能会有帮助,只是想一想。另一个问题是
std::cout@Lol4t0,这是因为
sizeof()
在编译时不计算它的参数。您的
OutputIterator
类型可能与
InputIterator
类型完全不同,它取决于操作员的返回type@Lol4t0这只取决于OutIt是否可以转换为InIt。你没有抓住要点:
OutputIterator
类型可以与
InputIterator
类型完全不同,但是
std:transform
仍然可以工作(并且验证将失败)。还要注意,
std::is_const;标准::is_const;标准::is_const也不工作:(@rhalbersma:谢谢你的回答,但我真正想验证的是
std::transform
的实现是否符合其规范,而不是某个特定参数
是否为常量。根据你的解释,听起来我可能无法。这是一个很好的技巧。你可能想将此答案发布到这个相关的任务中ion(Q已经2年了,但OP仍然处于活动状态)更新:另请参阅,以获得稍微不同的解决方案。@rhalbersma,很好的链接。修复了
std::iterator\u traits
issue.:。我将答案留在这里,以供参考。
template <typename T>
struct is_const
{
    enum {value = false };
};

template <typename T>
struct is_const<const T>
{
    enum {value = true };

};
template <typename Iterator>
struct is_iterator_constant
{
    typedef char yes_type;
    typedef struct{ char _[2];}  no_type;
    template <typename T>
    static no_type test(T&);

    template <typename T>
    static yes_type test(...);

    enum {value = sizeof(test<typename std::iterator_traits<Iterator>::value_type>(*Iterator())) == sizeof(yes_type) };

};