2013-07-26 30 views
3

所以在過去的幾個星期裏,我一直在嘗試使用函數式編程類型的解決方案來解決C++ 11中的問題,而且我時常處於一種情況我需要一個返回一個常量值的函數。C++中的類似於Haskell的`const`

在Haskell中,有一個函數

const :: a -> b -> a 
const x = \_ -> x 

返回計算結果爲常量的原始說法,無論是什麼參數提供給它的功能。我想在C++ 11中創建類似的東西。這樣的構造對於表示函數中的特殊行爲是有用的(發送給過濾器的常量函數將保持數據完整)。這是我第一次嘗試:

template<class T> 
std::function<T(...)> constF(T x) { 
    return ([x](...) { return x; }); 
} 

這將編譯自身,但使用它會導致不完全型錯誤的任何企圖。我的第二次嘗試是這樣的:

template<class T, class... Args> 
std::function<T(Args...)> constF(T x) { 
    return ([x](Args...) { return x; }); 
} 

這更接近,但不允許我提供任何參數,除非我明確聲明它們。

auto trueFunc1 = constF(true); 
auto trueFunc2 = constF<bool, int>(true); 
cout << trueFunc1() << endl; //works 
cout << trueFunc1(12) << endl; //doesn't compile 
cout << trueFunc2(12) << endl; //works 

理想情況下,正確的構造不會在trueFunc1和trueFunc2之間產生差異。

這甚至可能在C++?

回答

5

由於C++ 11並沒有通用的或可變參數的lambda,我會寫一個仿函數模板類:

template <typename T> 
// requires CopyConstructible<T> 
class const_function { 
    T value; 
public: 
    template <typename U, typename = typename std::enable_if<std::is_convertible<U,T>::value>::type> 
    const_function(U&& val) : 
    value(std::forward<U>(val)) {} 

    template <typename... Args> 
    T operator() (Args&&...) const { 
    return value; 
    } 
}; 

和一個不錯的類型推斷的包裝,使他們:

template <typename T> 
const_function<typename std::remove_reference<T>::type> 
constF(T&& t) { 
    return {std::forward<T>(t)}; 
} 

在C++ 1Y,我想簡單的等效是:

template <typename T> 
auto constF(T&& t) { 
    return [t{std::forward<T>(t)}](auto&&...){return t;}; 
} 
+0

布萊什,曾在一些'enable_if'拋出這樣我的過分熱心的完美轉發構造函數不會破壞'const_function'的拷貝構造。 – Casey

+0

你可以讓'constF(「abracadabra」)(42)'工作嗎? :) –

+0

@ n.m。不容易,因爲我很懶,儘管'constF (「abracadabra」)(42)'是一個簡單的解決方法。 – Casey