Bazı callable'ların ilk parametresi olarak bir referans referans alıp almadığını anlatan bir özellik yazmaya çalışıyorum. Bu, bazı meta programlamanın, callable'ın harici kod tarafından sağlandığı satılabilirliği çağırırken (veya bir kullanıcı tarafından sağlanan callable tipte aşırı yüklenme), semantiklerin taşıma veya kopyalamanın kullanılıp kullanılmayacağını ayarlar.Bazı callable'ların bir referans referans alıp almadığı nasıl belirlenir?
#include <functional>
#include <iostream>
#include <type_traits>
// Does the callable when called with Arg move?
template<class F, class Arg> struct is_callable_moving
{
typedef typename std::decay<Arg>::type arg_type;
typedef typename std::function<F(arg_type)>::argument_type parameter_type;
static constexpr bool value = std::is_rvalue_reference<parameter_type>::value;
};
int main(void)
{
auto normal = [](auto) {}; // Takes an unconstrained input.
auto moving = [](auto&&) {}; // Takes a constrained to rvalue ref input.
std::cout << "normal=" << is_callable_moving<decltype(normal), int>::value << std::endl;
std::cout << "moving=" << is_callable_moving<decltype(moving), int>::value << std::endl; // should be 1, but isn't
getchar();
return 0;
}
yukarıdaki açıkçası çalışmıyor ama umarım aradığım şeyi açıklıyor: Yalnızca bir rvalue referans olmasının onların parametresini kısıtlayan callables algılamak istiyorum.
Get lambda parameter type gibi diğer Yığın Taşması yanıtlarının burada yararlı olmadığına dikkat edin çünkü C++ 14 genel lambdalarını (yani, otomatik parametreleri alan) desteklemem gerekiyor ve bu nedenle de telefon operatörü lambda'nın adresini alarak temel almayı tipi aşırı yükü giderememekle başarısız olur.
is_callable_working'in bir Arg türü aldığını ve callable F'nin doğru aşırı yüklenmesinin F(Arg)
aracılığıyla bulunacağını unutmayın. Ben algılamak istiyorum şey F(Arg)
için kullanılabilir aşırı bir F::operator()(Arg &&)
veya Arg>)
için F::operator()(
< başka başvuru türü olup olmadığıdır. F()
için belirsiz aşırı yükler mevcutsa, örn. hem F(Arg)
hem de F(Arg &&)
sonra derleyici hata yapar, ancak [](auto)
[](auto &&)
arasında belirsiz olmamalıdır.
Düzenleme: umarım sorumu açıklığa kavuşturuldu. C++ meta programlamanın argümanlar üzerindeki kısıtlamaları tespit edip edemeyeceğini gerçekten soruyorum.
Düzenleme 2: Burada bazı açıklama olduğunu.
template<class T> class monad
{
...
template<class U> monad<...> bind(U &&v);
};
monad<T>.bind([](T}{})
kopya ile T
alır ve ben monad<T>.bind([](T &&){})
rvalue referans olarak T
alır istiyorum (yani çağrılabilir ondan hareket olabilir): My tam kullanım durumunda budur.
Yukarıda da belirtildiği gibi, monad<T>.bind([](auto){})
'un kopyalayarak T'yi almasını ve monad<T>.bind([](auto &&){})
'un r değerini referans alarak almasını istiyorum.
bu, farklı etkiler belirtilen nasıl çağrılabilir bağlı olarak oluşan ve böylece monad<T>.bind()
arasında aşırı bir tür. Eğer birisi lambdalardan önce olabileceğimiz gibi, çağrı imzasına dayalı olarak bind()
'u aşırı yükleyebilseydi, tüm bunlar kolay olurdu. Burada sorun olan lambda tiplerini yakalamanın bilinmemesi ile uğraşıyor.
Her iki sonucu da sağlayan aşırı yüklü satırlar için ne tür bir sonuç beklersiniz? – Quentin
@Quentin: is_callable_moving içindeki ikinci parametrenin, doğru aşırı yüklenmeye sahip olması ve/veya otomatik lambda'nın doğru bir şekilde uygulanabilmesi için çağrılabilir olanı çağırmak için kullanılan argüman olduğunu not edebilirsiniz.Umut, geçici olarak (otomobili) bir şekilde callable (auto &&) 'den ayırt edilebilir olurdu. –
Satılabilirlik yalnızca bir argüman alır mı? –