我发现这里的代码看起来像这样:
auto f(T& t, size_t n) -> decltype(t.reserve(n), void()) { .. }
Run Code Online (Sandbox Code Playgroud)
在我阅读的所有文档中,我被告知decltype签名为:
decltype( entity )
要么
decltype( expression )
任何地方都没有第二个论点.至少这是cppreference所指出的.这是第二个参数decltype吗?如果是这样,它会做什么?
我正在尝试检测一个类是否具有特定的功能(具体来说shared_from_this(),是继承自哪个std::enable_shared_from_this<Some Unknown Class>).为了使事情变得更复杂,我需要知道它是否具有此功能,即使它已从远程基类继承或使用受保护访问继承.
我已经查看了其他问题,例如这个问题,但提供的方法不适用于检测受保护的成员函数.
我目前使用的方法如下:
template <class T>
struct shared_from_this_wrapper : public T
{
template <class U>
static auto check( U const & t ) -> decltype( t.shared_from_this(), std::true_type() );
static auto check( ... ) -> decltype( std::false_type() );
};
template<class T>
struct has_shared_from_this : decltype(shared_from_this_wrapper<T>::check(std::declval<shared_from_this_wrapper<T>>()))
{ };
Run Code Online (Sandbox Code Playgroud)
我当前解决方案的缺陷是它不适用于声明的类final.所以我正在寻找一个满足以下成员函数的测试解决方案:
final编辑:我有一个可行的解决方案,但需要与帮助类成为朋友,这也不是一个理想的解决方案,但现在可能是一种解决方法(因为它满足所有要求):
struct access
{
template <class T>
static auto shared_from_this( T const & t ) -> …Run Code Online (Sandbox Code Playgroud) 使用SFINAE,我可以检测给定的类是否具有某个成员函数.但是如果我想测试继承的成员函数呢?
以下在VC8和GCC4中不起作用(即检测到A具有成员函数foo(),但不会B继承成员函数):
#include <iostream>
template<typename T, typename Sig>
struct has_foo {
template <typename U, U> struct type_check;
template <typename V> static char (& chk(type_check<Sig, &V::foo>*))[1];
template <typename > static char (& chk(...))[2];
static bool const value = (sizeof(chk<T>(0)) == 1);
};
struct A {
void foo();
};
struct B : A {};
int main()
{
using namespace std;
cout << boolalpha << has_foo<A, void (A::*)()>::value << endl; // true
cout << boolalpha …Run Code Online (Sandbox Code Playgroud) 如果我做
struct A{};
struct C:private A{};
typedef char (&yes)[1];
typedef char (&no)[2];
template <typename B, typename D>
struct Host
{
operator B*() const;
operator D*();
};
template <typename B, typename D>
struct is_base_of
{
template <typename T>
static yes check(D*, T);
static no check(B*, int);
static const bool value = sizeof(check(Host<B,D>(), int())) == sizeof(yes);
};
int main(){
std::cout<<is_base_of<A,C>::value<<std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我得到一个1.我想C在私有时获得0,在公共A时获得1 .CA
[代码源自`is_base_of`是如何工作的?]
使用gcc 4.7和boost 1.49时,使用以下表达式is_assignable返回true:
typedef boost::function<void()> F;
std::is_assignable<F, std::nullptr_t>::value
Run Code Online (Sandbox Code Playgroud)
但是,此代码无法编译:
boost::function<void()> f;
f = nullptr;
Run Code Online (Sandbox Code Playgroud)
产生以下错误消息:
In file included from c:\mingw\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/boost/function/detail/maybe_include.hpp:13:0,
from c:\mingw\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/boost/function/detail/function_iterate.hpp:14,
from c:\mingw\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/boost/preprocessor/iteration/detail/iter/forward1.hpp:47,
from c:\mingw\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/boost/function.hpp:64,
from ..\main.cpp:8:
c:\mingw\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/boost/function/function_template.hpp: In instantiation of 'static void boost::detail::function::void_function_obj_invoker0<FunctionObj, R>::invoke(boost::detail::function::function_buffer&) [with FunctionObj = std::nullptr_t; R = void]':
c:\mingw\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/boost/function/function_template.hpp:907:60: required from 'void boost::function0<R>::assign_to(Functor) [with Functor = std::nullptr_t; R = void]'
c:\mingw\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/boost/function/function_template.hpp:722:7: required from 'boost::function0<R>::function0(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = std::nullptr_t; R = void; typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]'
c:\mingw\bin\../lib/gcc/i686-pc-mingw32/4.7.0/../../../../include/boost/function/function_template.hpp:1042:16: required …Run Code Online (Sandbox Code Playgroud) 读马修的回答后在这里,我决定试试这个自己.
我的尝试无法编译,因为SFINAE没有启动并剔除has_foo尝试访问的功能T::foo.
error: ‘struct Bar’ has no member named ‘foo’
Run Code Online (Sandbox Code Playgroud)
我错过了什么,或者是我试图以这种方式做不到的事情?
(我正在使用gcc-4.7.2)
完整示例如下:
#include <iostream>
// culled by SFINAE if foo does not exist
template<typename T>
constexpr auto has_foo(T& t) -> decltype((void)t.foo, bool())
{
return true;
}
// catch-all fallback for items with no foo
constexpr bool has_foo(...)
{
return false;
}
//-----------------------------------------------------
template<typename T, bool>
struct GetFoo
{
static int value(T& t)
{
return t.foo;
}
};
template<typename T>
struct GetFoo<T, false>
{ …Run Code Online (Sandbox Code Playgroud) 我正在使用一个简单的SFINAE技巧来检查成员函数是否存在,如下所示:
#include <type_traits>
template <typename C>
struct has_size {
template <typename T>
static constexpr auto check(T*) ->
decltype(std::declval<T const>().size(), std::true_type{});
template <typename>
static constexpr auto check(...) -> std::false_type;
static constexpr bool value = decltype(check<C>(nullptr))::value;
};
// Usage:
static_assert(has_size<std::vector<int>>::value, "std::vector<int> has size()");
Run Code Online (Sandbox Code Playgroud)
(我知道现在有一种更简单的方法,但是当我编写这段代码时却没有回来.)
此代码适用于GCC.然而,Clang发出警告1(Apple LLVM 7.3以上的所有版本,无论哪个是上游版本):
decltype.cpp:15:27: error: inline function 'has_size<std::__1::vector<int, std::__1::allocator<int> > >::check<std::__1::vector<int, std::__1::allocator<int> > >' is not defined [-Werror,-Wundefined-inline]
static constexpr auto check(T*) ->
^
decltype.cpp:22:44: note: used here
static constexpr bool value = decltype(check<C>(nullptr))::value; …Run Code Online (Sandbox Code Playgroud) 让我们从一个代码开始(请注意缩短以仅显示有问题的部分).
#include <type_traits>
#include <utility>
#include <list>
#include <forward_list>
#include <functional>
template<typename Container, typename Compare>
class SortedContainer
{
public:
template<typename... Args>
auto erase(Args&&... args) -> decltype(std::declval<Container>().erase(std::forward<Args>(args)...))
{
return container_.erase(std::forward<Args>(args)...);
}
decltype(std::declval<const Container>().size()) size() const
{
return container_.size();
}
private:
/// container used for keeping elements
Container container_;
};
SortedContainer<std::list<int>, std::less<int>> list;
SortedContainer<std::forward_list<int>, std::less<int>> forward_list;
int main()
{
}
Run Code Online (Sandbox Code Playgroud)
SortedContainer如果底层Container没有匹配签名所需的函数,我想有选择地禁用模板中的一些函数.
上面的例子失败了,因为std::forward_list没有erase()和size()函数:
$ g++ -std=c++11 test.cpp
test.cpp: In instantiation of ‘class SortedContainer<std::forward_list<int>, std::less<int> …Run Code Online (Sandbox Code Playgroud)