2016-04-04 13 views
2

Sorduğum şey muhtemelen imkansız, ancak emin olmak için soruyorum. Bu soruda daha önce sorulduğu ve yanıtlandığı gibi: SFINAE and decltype(auto), bir otomatik döndürme türüyle işlevler SFINAE olmayabilir, çünkü dönüş türünün kesintisi bir şablon örneğine neden olur. Örnekleme sırasında derleyici bir hata üretecektir. Bununla birlikte, belki de birileri, bir kod parçasında bir örnekleme hatasını bir başkasında bir ikame arızasına dönüştürmek için çılgın bir hileden bilirler ve bu nedenle de SFINAE'yi teşvik ederler mi? the code on Godbolt here etrafındaSFINAE?

#include <utility> 

struct no_call_ops { }; 

struct caller 
{ 
    // Goal is to detect whether a particular Handler type 
    // will be ok to pass into caller 
    template <typename Handler> 
    auto operator() (Handler&& handler, int v) 
    { 
     handler(3.14); 

     while (v--) 
     { 
      handler("hello world"); 
     } 

     // etc... 
     // more calls to handler that I don't want to 
     // express in the trailing return type. 
    } 
}; 

struct fallback { }; 

struct tester 
{ 
    // Would be nice if this fails substitution... 
    template <typename Caller, typename Handler, typename... Args> 
    auto operator() (Caller&& caller, Handler&& handler, Args&&... args) 
     -> decltype(caller(handler, std::forward<Args>(args)...)) 
    { } 

    fallback operator() (...) { return fallback{}; } 
}; 

// want detected_t to be "fallback" 
using detected_t = decltype(tester{}(caller{}, no_call_ops{}, 42)); 

Play:

İşte bir hataya neden olan bir örnek olarak kodu parçasıdır, bu.

Teşekkür ederiz!

+0

Ne olmak istersiniz? no_call_ops bir operatöre() sahip değildir, bu yüzden arama denemesi bir hatadır. SFINAE, yalnızca içerdiği kodda değil, bir işlev/türün veri türü üzerinde çalışır. Handler'ın geri aradığına emin olmak için operatörünüze() sfinae koyabilirsiniz, ancak istediğinizin olduğundan emin değilim. MAYBE – xaxxon

+0

Sanırım yapmaya çalıştığım şey, içerdiği kodda SFINAE. Sonuç olarak her şey derler ve 'detected_t'' fallback' türündedir. Bu yüzden, bunun imkansız olabileceğini düşünüyorum çünkü derleyiciden, ortaya çıkardığı kodu atmasını rica ediyorum. Yapmaya çalıştığım şeyi daha fazla motive etmek için, işleyiciye farklı türlerde birkaç kez çağrıldığını hayal edin. Orada bir geri dönüş tipi yaratmak istemiyorum çünkü ifade etmem için çok karmaşık olurdu. –

+0

Tam olarak ne yaptığımı bilmiyorum ... https://godbolt.org/g/v4Mn5i ama ben bir geri dönüş tipi kullanmıştım. – xaxxon

cevap

0

Bu geri dönüş türü kabul edilebilir mi?

#include <utility> 
#include <functional> 
using namespace std; 

struct no_call_ops { }; 

template<class T> 
using int_t = int; 

struct caller 
{ 
    template <typename Handler, int_t<typename result_of<Handler>::type> = 0> 
    auto operator() (Handler&& handler, int) -> typename result_of<Handler>::type 
    { 
    handler(3.14);  
    } 
}; 


struct fallback { }; 

struct tester 
{ 
    template <typename Caller, typename Handler, typename... Args> 
    auto operator() (Caller&& caller, Handler&& handler, Args&&... args) -> decltype(caller(handler, std::forward<Args>(args)...)) 
    { } 

    fallback operator() (...) { return fallback{}; } 
}; 

using detected_t = decltype(tester{}(caller{}, no_call_ops{}, 42)); 
+0

için mevcut olduğu garanti edilmez. Bir dizi declval şeyler yapmak zorunda kalmayı kolaylaştırmak için işleyiciyi std :: işlevine uygun giriş türleriyle doldurmayı deneyebilirsiniz. ya da bir parametre paketini geçirip () ... – xaxxon

0

Bu sizin için çalışır mı?

#include <utility> 

struct no_call_ops { }; 

struct caller 
{ 
    template <typename Handler, class = decltype(std::declval<Handler>()(3.14))> 
    decltype(auto) operator() (Handler&& handler, int) 
    { 
    handler(3.14);  
    } 
}; 

struct fallback { }; 

struct tester 
{ 
    template <typename Caller, typename Handler, typename... Args> 
    auto operator() (Caller&& caller, Handler&& handler, Args&&... args) -> decltype(caller(handler, std::forward<Args>(args)...)) 
    { } 

    fallback operator() (...) { return fallback{}; } 
}; 

using detected_t = decltype(tester{}(caller{}, no_call_ops{}, 42)); 
İlgili konular