Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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++函数,代码< iS>可调用< /COD>,定义值>代码> >代码>真/ ,如果类型f只有函数名调用操作符的形式:代码> SoMeTururnType操作器()(const ARG&)。例如,在以下情况下 struct foo { void operator(const int &) {} };_C++_Templates_C++11_Template Meta Programming_Sfinae - Fatal编程技术网

我如何确定一个类型是否只能用常量引用调用? < >我想编写一个C++函数,代码< iS>可调用< /COD>,定义值>代码> >代码>真/ ,如果类型f只有函数名调用操作符的形式:代码> SoMeTururnType操作器()(const ARG&)。例如,在以下情况下 struct foo { void operator(const int &) {} };

我如何确定一个类型是否只能用常量引用调用? < >我想编写一个C++函数,代码< iS>可调用< /COD>,定义值>代码> >代码>真/ ,如果类型f只有函数名调用操作符的形式:代码> SoMeTururnType操作器()(const ARG&)。例如,在以下情况下 struct foo { void operator(const int &) {} };,c++,templates,c++11,template-meta-programming,sfinae,C++,Templates,C++11,Template Meta Programming,Sfinae,我希望可调用为假且可调用为真。这就是我到目前为止所做的: #include <memory> #include <iostream> template<typename F, typename Arg> struct is_callable { private: template<typename> static char (&test(...))[2]; template<unsigned> struct

我希望
可调用
可调用
。这就是我到目前为止所做的:

#include <memory>
#include <iostream>

template<typename F, typename Arg>
struct is_callable {
private:

  template<typename>
  static char (&test(...))[2];

  template<unsigned>
  struct helper {
    typedef void *type;
  };

  template<typename UVisitor>
  static char test(
               typename helper<
                 sizeof(std::declval<UVisitor>()(std::declval<Arg>()), 0)
                 >::type
               );
public:
  static const bool value = (sizeof(test<F>(0)) == sizeof(char));
};

struct foo {
  void operator()(const int &) {}
};

using namespace std;

int main(void)
{
  cout << is_callable<foo, int &>::value << "\n";
  cout << is_callable<foo, const int &>::value << "\n";

  return 0;
}
#包括
#包括
模板
结构是可调用的{
私人:
模板
静态字符(&测试(…)[2];
模板
结构辅助程序{
typedef void*类型;
};
模板
静态煤焦试验(
类型名助手<
sizeof(std::declval()(std::declval()),0)
>::类型
);
公众:
静态常量布尔值=(sizeof(test(0))==sizeof(char));
};
结构foo{
void运算符()(常量int&){}
};
使用名称空间std;
内部主(空)
{

也许可以这样做吗?要想在VS2010上使用它还需要一些时间

template<typename FPtr>
struct function_traits_impl;

template<typename R, typename A1>
struct function_traits_impl<R (*)(A1)>
{
    typedef A1 arg1_type;
};

template<typename R, typename C, typename A1>
struct function_traits_impl<R (C::*)(A1)>
{
    typedef A1 arg1_type;
};

template<typename R, typename C, typename A1>
struct function_traits_impl<R (C::*)(A1) const>
{
    typedef A1 arg1_type;
};

template<typename T>
typename function_traits_impl<T>::arg1_type arg1_type_helper(T);

template<typename F>
struct function_traits
{
    typedef decltype(arg1_type_helper(&F::operator())) arg1_type;
};

template<typename F, typename Arg>
struct is_callable : public std::is_same<typename function_traits<F>::arg1_type, const Arg&>
{
}
模板
结构-功能-特征-实现;
模板
结构函数
{
类型定义A1 arg1_类型;
};
模板
结构函数
{
类型定义A1 arg1_类型;
};
模板
结构函数
{
类型定义A1 arg1_类型;
};
模板
类型名函数\u traits\u impl::arg1\u type arg1\u type\u helper(T);
模板
结构功能特性
{
typedef decltype(arg1_type_helper(&F::operator())arg1_type;
};
模板
结构是可调用的:public std::是相同的吗
{
}

这里有一个我破解的东西,它可能是你需要的,也可能不是你需要的;它似乎给出了
(const)int&
的真(假)值

#include <utility>

template <typename F, typename Arg>
struct Callable
{
private:
  typedef char                      yes;
  typedef struct { char array[2]; } no;

  template <typename G, typename Brg>
  static yes test(decltype(std::declval<G>()(std::declval<Brg>())) *);

  template <typename G, typename Brg>
  static no test(...);

public:
  static bool const value = sizeof(test<F, Arg>(nullptr)) == sizeof(yes);
};

struct Foo
{
  int operator()(int &) { return 1; }
  // int operator()(int const &) const { return 2; } // enable and compare
};

#include <iostream>
int main()
{
  std::cout << "Foo(const int &): " << Callable<Foo, int const &>::value << std::endl
            << "Foo(int &):       " << Callable<Foo, int &>::value << std::endl
    ;
}
#包括
模板
结构可调用
{
私人:
typedef char是;
typedef结构{char数组[2];}否;
模板
静态yes测试(decltype(std::declval()(std::declval())*);
模板
静态无试验(…);
公众:
静态布尔常量值=sizeof(test(nullptr))==sizeof(yes);
};
结构Foo
{
int运算符()(int&{return 1;}
//int operator()(int const&)const{return 2;}//启用并比较
};
#包括
int main()
{
std::cout(对Kerrek以他的答案作为出发点表示歉意)

编辑:更新为处理类型而不使用任何
运算符()

#include <utility>

template <typename F, typename Arg>
struct Callable
{
private:
  static int tester[1];
  typedef char                      yes;
  typedef struct { char array[2]; } no;

  template <typename G, typename Brg>
  static char sfinae(decltype(std::declval<G>()(std::declval<Brg>())) (G::*pfn)(Brg)) { return 0; }

  template <typename G, typename Brg>
  static char sfinae(decltype(std::declval<G>()(std::declval<Brg>())) (G::*pfn)(Brg) const) { return 0; }

  template <typename G, typename Brg>
  static yes test(int (&a)[sizeof(sfinae<G,Brg>(&G::operator()))]);

  template <typename G, typename Brg>
  static no test(...);

public:
  static bool const value = sizeof(test<F, Arg>(tester)) == sizeof(yes);
};

struct Foo
{
  int operator()(int &) { return 1; }

};

struct Bar
{
  int operator()(int const &) { return 2; }
};

struct Wazz
{
  int operator()(int const &) const { return 3; }
};

struct Frob
{
  int operator()(int &) { return 4; }
  int operator()(int const &) const { return 5; }
};

struct Blip
{
  template<typename T>
  int operator()(T) { return 6; }
};

struct Boom
{

};

struct Zap
{
  int operator()(int) { return 42; }
};

#include <iostream>
int main()
{
  std::cout << "Foo(const int &):  " << Callable<Foo,  int const &>::value << std::endl
            << "Foo(int &):        " << Callable<Foo,  int &>::value << std::endl
            << "Bar(const int &):  " << Callable<Bar,  const int &>::value << std::endl
            << "Bar(int &):        " << Callable<Bar,  int &>::value << std::endl
            << "Zap(const int &):  " << Callable<Zap , const int &>::value << std::endl
            << "Zap(int&):         " << Callable<Zap , int &>::value << std::endl
            << "Wazz(const int &): " << Callable<Wazz, const int &>::value << std::endl
            << "Wazz(int &):       " << Callable<Wazz, int &>::value << std::endl
            << "Frob(const int &): " << Callable<Frob, const int &>::value << std::endl
            << "Frob(int &):       " << Callable<Frob, int &>::value << std::endl
            << "Blip(const int &): " << Callable<Blip, const int &>::value << std::endl
            << "Blip(int &):       " << Callable<Blip, int &>::value << std::endl
            << "Boom(const int &): " << Callable<Boom, const int &>::value << std::endl
            << "Boom(int&):        " << Callable<Boom, int &>::value << std::endl;
}
#包括
模板
结构可调用
{
私人:
静态int测试仪[1];
typedef char是;
typedef结构{char数组[2];}否;
模板
静态字符sfinae(decltype(std::declval()(std::declval())(G::*pfn)(Brg)){return 0;}
模板
静态字符sfinae(decltype(std::declval()(std::declval())(G::*pfn)(Brg)const){return 0;}
模板
静态yes测试(int(&a)[sizeof(sfinae(&G::operator())]);
模板
静态无试验(…);
公众:
静态布尔常量值=sizeof(测试仪))==sizeof(是);
};
结构Foo
{
int运算符()(int&{return 1;}
};
结构条
{
int运算符()(int常量&){return 2;}
};
结构Wazz
{
int运算符()(int const&)const{return 3;}
};
结构泡沫
{
int运算符()(int&{return 4;}
int运算符()(int const&)const{return 5;}
};
结构光点
{
模板
int运算符()(T){return 6;}
};
结构吊杆
{
};
结构Zap
{
int运算符()(int){return 42;}
};
#包括
int main()
{

std::cout这里有一个可能的解决方案,它利用一个额外的测试来查看您的模板是否正在使用一个
常量进行实例化&

#include <memory>
#include <iostream>

using namespace std;

template<typename F, typename Arg>
struct is_callable {
private:

  template<typename>
  static char (&test(...))[2];

  template<bool, unsigned value>
  struct helper {};

  template<unsigned value>
  struct helper<true, value> {
    typedef void *type;
  };

  template<typename T>
  struct is_const_ref {};

  template<typename T>
  struct is_const_ref<T&> {
    static const bool value = false;
  };

  template<typename T>
  struct is_const_ref<const T&> {
    static const bool value = true;
  };

  template<typename UVisitor>
  static char test(typename helper<is_const_ref<Arg>::value, 
                                   sizeof(std::declval<UVisitor>()(std::declval<Arg>()), 0)>::type);
public:
  static const bool value = (sizeof(test<F>(0)) == sizeof(char));
};

struct foo {
  void operator()(const int &) {}
};

int main(void)
{
  cout << is_callable<foo, int &>::value << "\n";
  cout << is_callable<foo, const int &>::value << "\n";

  return 0;
}
#包括
#包括
使用名称空间std;
模板
结构是可调用的{
私人:
模板
静态字符(&测试(…)[2];
模板
结构助手{};
模板
结构辅助程序{
typedef void*类型;
};
模板
结构是_const_ref{};
模板
结构是常数{
静态常量布尔值=假;
};
模板
结构是常数{
静态常量布尔值=真;
};
模板
静态字符测试(typename助手::type);
公众:
静态常量布尔值=(sizeof(test(0))==sizeof(char));
};
结构foo{
void运算符()(常量int&){}
};
内部主(空)
{

cout经过几个小时的反复研究,我们终于得到了一个版本,它适用于可能重载或继承了
操作符()
的函子以及基于@KerrekSB和@BenVoigt版本的函数指针

#include <utility>
#include <type_traits>

template <typename F, typename... Args>
class Callable{
  static int tester[1];
  typedef char yes;
  typedef yes (&no)[2];

  template <typename G, typename... Brgs, typename C>
  static typename std::enable_if<!std::is_same<G,C>::value, char>::type
      sfinae(decltype(std::declval<G>()(std::declval<Brgs>()...)) (C::*pfn)(Brgs...));

  template <typename G, typename... Brgs, typename C>
  static typename std::enable_if<!std::is_same<G,C>::value, char>::type
      sfinae(decltype(std::declval<G>()(std::declval<Brgs>()...)) (C::*pfn)(Brgs...) const);

  template <typename G, typename... Brgs>
  static char sfinae(decltype(std::declval<G>()(std::declval<Brgs>()...)) (G::*pfn)(Brgs...));

  template <typename G, typename... Brgs>
  static char sfinae(decltype(std::declval<G>()(std::declval<Brgs>()...)) (G::*pfn)(Brgs...) const);

  template <typename G, typename... Brgs>
  static yes test(int (&a)[sizeof(sfinae<G,Brgs...>(&G::operator()))]);

  template <typename G, typename... Brgs>
  static no test(...);

public:
  static bool const value = sizeof(test<F, Args...>(tester)) == sizeof(yes);
};

template<class R, class... Args>
struct Helper{ R operator()(Args...); };
 
template<typename R, typename... FArgs, typename... Args>
class Callable<R(*)(FArgs...), Args...>
  : public Callable<Helper<R, FArgs...>, Args...>{};
#包括
#包括
模板
类可调用{
静态int测试仪[1];
typedef char是;
typedef是和否[2];
模板
静态类型名称std::enable_if::value,char>::type
sfinae(decltype(std::declval()(std::declval()…)(C::*pfn)(Brgs…);
模板
静态类型名称std::enable_if::value,char>::type
sfinae(decltype(std::declval()(std::declval())(C::*pfn)(Brgs…)const);
模板
静态字符sfinae(decltype(std::declval()(std::declval()…)(G::*pfn)(Brgs…);
模板
静态字符sfinae(decltype(std::declval()(std::declval())(G::*pfn)(Brgs…)常量);
模板
静态yes测试(int(&a)[sizeof(sfinae(&G::operator())]);
模板
静态无试验(…);
公众:
静态布尔常量值=sizeof(测试仪))==sizeof(是);
};
模板
结构帮助器{R运算符()(Args…;};
模板
类可调用
:公共可调用{};
。请注意,这两个失败的测试是重载的
operator()
tests。这是一个带有可变模板的GCC错误,已在GCC 4.7中修复。Clang 3.1还将所有测试报告为
通过

如果您想让带有默认参数的
operator()
失败,有一种可能的方法可以做到这一点,但是其他一些测试将在这一点上开始失败,我发现尝试并纠正这一点太麻烦了

编辑:正如@Johannes在评论中正确地指出的,我们在这里有一点不一致,即不会被检测为“可调用”。这是,嗯,非常不容易修复的,因此我现在不想麻烦它。如果你真的需要这个特性,那么,请留下评论,我会看看有什么
#include <type_traits>
#include <functional>

namespace detail {
  template<typename T, class Args, class Enable=void>
  struct call_exact : std::false_type {};

  template<class...Args> struct ARGS { typedef void type; };

  template<class T, class ... Args, class C=T>
  C * opclass(decltype(std::declval<T>()(std::declval<Args>()...)) (C::*)(Args...)) { }
  template<class T, class ... Args, class C=T>
  C * opclass(decltype(std::declval<T>()(std::declval<Args>()...)) (C::*)(Args...) const) { }

  template<typename T, class ... Args>
  struct call_exact<T, ARGS<Args...>,
    typename ARGS<
       decltype(std::declval<T&>()(std::declval<Args>()...)),
       decltype(opclass<T, Args...>(&T::operator()))
     >::type
   > : std::true_type {};
}

template<class T, class ... Args>
struct Callable : detail::call_exact<T, detail::ARGS<Args...>> { };

template<typename R, typename... FArgs, typename... Args>
struct Callable<R(*)(FArgs...), Args...>
 : Callable<std::function<R(FArgs...)>, Args...>{};