2016-03-22 41 views
0

Şablon bağımsız değişken olarak geçirilen işlev türünün bağımsız değişkenleri değiştirmemesi nasıl sağlanır?

template<typename FunctionType> 
void foo(FunctionType && function) 
{ 
    Bar b; 
    bar.mutateState(); 
    function(bar); 
} 

Ben functionbar mutasyona olmadığından emin olmak için, bu şablonu düşünün. Aşağıdakiler derlenmemelidir. Ancak, her iki satır da derlenmelidir.

foo([](const Bar &){}); 
foo([](Bar){}); 

Hangi teknikler kullanılabilir? Daha basittir, ancak std::function üzerinden şablon tipi içgözlemeyi veya işaretçi imzasını tercih ederim.

Sen bar bir const sürümü ile function aramaya foo değiştirebilir

cevap

2

yapmanız olabilir:

template<typename FunctionType> 
auto foo(FunctionType && function) 
-> decltype(function(std::declval<const Bar&>()), void()) 
{ 
    Bar bar; 
    bar.mutateState(); 
    function(bar); 
} 
+1

Bu işlev, gereksinim duyulduğu veya yanlışlıkla silinebileceği uygulamada gömmek yerine, işlev bildirgesine daha açık bir şekilde gereksinim duymak istiyorsanız iyi bir alternatiftir. – Mankarse

3

:

template<typename FunctionType> 
void foo(FunctionType && function) 
{ 
    Bar bar; 
    bar.mutateState(); 
    auto const & c_bar = bar; 
    function(c_bar); 
} 
+0

11 C++ için bu gayet iyi. C++ 11'den önce "Bar const & c_bar" veya "const Bar & c_bar = bar" gereklidir. Herkes C++ 11'e geçemez. – Peter

+0

@Peter question.has 'C++ 11' etiketi –

+0

Biliyorum Revolver. Ayrıca bir C++ etiketi var. C++ ve C++ 11 eş anlamlı değildir. – Peter

0

Sadece ben Anlaşılan bu std::as_const olarak C++17 başlıkları aşağıdaki gibidir

template<typename T> 
typename std::add_const<T>::type &asConst(T &t) 
{ 
    return t; 
} 

template<typename FunctionType> 
void Foo(FunctionType && function) 
{ 
    Bar bar; 
    bar.mutateState(); 
    function(asConst(bar)); 
} 

yapabileceğini fark yazdıktan sonra .

3

basit yöntemi (C++ 17 beri) as_const yarar işlevini kullanmak olacaktır:

template<typename FunctionType> 
void foo(FunctionType && function) 
{ 
    Bar b; 
    bar.mutateState(); 
    function(std::as_const(bar)); 
} 
0

Sen türü hakkında açık olabilir.

SFINAE ile
#pragma once 

class Bar 
{ 
    int a; 
public: 
    Bar() : a{0} 
    {} 
    void mutateState() 
    { 
     ++a; 
    } 
}; 

void foo(void(*function)(const Bar &)) 
{ 
    Bar bar; 
    bar.mutateState(); 
    function(bar); 
} 

int main() 
{ 
    foo([](const Bar &) 
    {}); 
    foo([](Bar) 
    {}); 
} 
+0

Eğer lambda herhangi bir değişken yakaladığında bu işe yaramaz (işlev göstericisine örtülü dönüştürme devre dışı bırakılacak). – Mankarse

+0

@Mankarse Ah, bunu düşünmedim. – Johannes

İlgili konular