2016-02-03 81 views
0

我想定義一個函數,它將根據字符串的內容返回所需的類型運算符。我已經試過這一點,但它不工作:返回推力二進制函數

impl.cpp

template <typename T> thrust::binary_function<T,T,bool> 
get_filter_operator(const std::string &op) 
    if (op == "!=") 
     return thrust::not_equal_to<T>(); 
    else if (op == ">") 
     return thrust::greater<T>(); 
    else if (op == "<") 
     return thrust::less<T>(); 
    else if (op == ">=") 
     return thrust::greater_equal<T>(); 
    else if (op == "<=") 
     return thrust::less_equal<T>(); 
    else 
    { 
     return thrust::equal_to<T>(); 
    } 

template thrust::binary_function<float,float,bool> get_filter_operator<float>(const std::string &); 

impl.h

template <typename T> thrust::binary_function<T, T, bool> get_filter_operator(const std::string &op); 

我怎樣才能返回一個指向任意函數像thrust::not_equal_to<int>(),或thrust::equal_to<int>()?我找不到要返回的正確類型。

EDIT

按照要求,編譯器錯誤:

在「推力::的實例binary_function < T,T,布爾> get_filter_operator(常量字符串&)[用T =浮子;的std :: string =標準:: basic_string的<炭>] ':

錯誤:無法將 '推力:: equal_to <浮子>()' 從 '推力:: equal_to <浮子>' 到' 推力:: binary_function <浮動,浮動,布爾>」 回報推力:: equal_to()

更新

好抱歉沒有提及這之前:這個問題是我不能使用std ::函數,因爲它只適用於主機代碼。我想使用推力二進制函數,以便我可以在GPU和CPU中使用它們。

+1

我可以告訴你這個使用函數的近似值,但它不是真的回答你的問題。 –

+1

我認爲獲得你想要的最直接的方法是編寫一個仿函數,在所需的過濾器運算符上做一個「開關」。我不認爲'推力:not_equal_to'和朋友們在這裏幫助很大。 –

+0

實際上,我最終這樣做了。我想知道是否有一個更優雅的方式 – gumlym

回答

2

How can I return a pointer to an arbitrary function like thrust::not_equal_to(), or thrust::equal_to()? I cant find the correct type to return

每個您正在試圖返回的東西是兩個參數, 各某種類型的T,返回bool的功能。正確的返回類型爲

std::function<bool(T, T)> 

如:

#include <thrust/functional.h> 
#include <functional> 
#include <string> 

template<typename T> 
std::function<bool(T, T)> 
get_filter_operator(const std::string &op) 
{ 
    if (op == "!=") 
     return thrust::not_equal_to<T>(); 
    else if (op == ">") 
     return thrust::greater<T>(); 
    else if (op == "<") 
     return thrust::less<T>(); 
    else if (op == ">=") 
     return thrust::greater_equal<T>(); 
    else if (op == "<=") 
     return thrust::less_equal<T>(); 
    else 
    { 
     return thrust::equal_to<T>(); 
    } 
} 

#include <iostream> 

using namespace std; 

int main() 
{ 
    auto relop = get_filter_operator<int>("!="); 
    cout << boolalpha << relop(1,0) << endl; 
    cout << boolalpha << relop(1,1) << endl; 

    return 0; 
} 

現在,您可能希望您的評論再次重申對@MohamadElghawi:

Yeah, I knew that worked, but the problem is that I'm trying to return a thrust::binary_function, not from std

這可能是你是什麼試圖去做,但這是錯誤的事情,試圖做和不可能做的事情。請參閱<thrust/functional>中的 template<typename A1, typename A2, typename R> struct thrust::binary_function 以及相關文檔的定義。注:

binary_function is an empty base class: it contains no member functions or member variables, but only type information

特別是thrust::binary_function<A1,A2,R>沒有operator()。 它不可調用。它不能存儲任何其他可調用對象(或任何東西)。另見equal_to,not_equal_to, 等在同一文件中的定義。binary_function不是它們中的任何一個的基礎。 沒有從任何人轉換到binary_function

注太:

binary_function is currently redundant with the C++ STL type std::binary_function. We reserve it here for potential additional functionality at a later date.

std::binary_function本身不贊成使用C++ 11和將在C++ 17被移除)。

thrust::binary_function<T,T,bool>不是你要找的。 std::function<bool(T, T)> 是。

std::function<bool(int, int)> f = thrust::greater<int>(); 

使得f封裝一個可調用的對象,它是一個thrust::greater<int>

後來

The problem with this is that it can only be used in host code doesnt it? The beauty of thrust binary functions is that they can be used both in the GPU and the CPU.

我想你可能是下的印象是,例如

std::function<bool(int, int)> f = thrust::greater<int>(); /*A*/ 

需要thrust::greater<int>和以某種方式降級它變成一個 std::function<bool(int, int)>具有類似但更受限 (「STD」)的執行能力。

沒有這樣的情況。一個std::function<bool(int, int)> foo簡直是 任何bar是調用帶有兩個參數是隱式 轉換爲int,並返回一些隱式轉換爲bool,插座 例如,如果:

std::function<bool(int, int)> foo = bar; 

然後當你打電話foo(i,j)你返回結果,如bool執行bar(i,j)。不是執行任何與bar(i,j)不同的任何方式 的結果。

因此,在上述/*A*/,通過包含的,並且通過被稱爲可調用的東西,f 推力二元函數;它thrust::greater<int>()。由foperator()調用 的方法是thrust::greater<int>::operator()

這裏是一個程序:

#include <thrust/functional.h> 
#include <functional> 
#include <iostream> 

using namespace std; 

int main() 
{ 
    auto thrust_greater_than_int = thrust::greater<int>(); 
    std::function<bool(int, int)> f = thrust_greater_than_int; 
    cout << "f " 
     << (f.target<thrust::greater<int>>() ? "calls" : "does not call") 
     << " a thrust::greater<int>" << endl; 
    cout << "f " 
     << (f.target<thrust::equal_to<int>>() ? "calls" : "does not call") 
     << " a thrust::equal_to<int>" << endl; 
    cout << "f " 
     << (f.target<std::greater<int>>() ? "calls" : "does not call") 
     << " an std::greater<int>" << endl; 
    cout << "f " 
     << (f.target<std::function<bool(int,int)>>() ? "calls" : "does not call") 
     << " an std::function<bool(int,int)>" << endl; 
    return 0; 
} 

存儲在一個std::function<bool(int, int)> f 一個thrust::greater<int>,然後通知您:

f calls a thrust::greater<int> 
f does not call a thrust::equal_to<int> 
f does not call an std::greater<int> 
f does not call an std::function<bool(int,int)> 
+0

這個問題是它只能用在主機代碼中嗎?推動二元函數的美妙之處在於它們可以在GPU和CPU中使用。否則,我會只使用std函數,而不是使用推力 – gumlym

+0

@gumlyn更新可以幫助。 –

+0

好的,對不起,沒有提到過,我沒有想到它 – gumlym

0

以下適用於我。

#include <iostream> 
#include <functional> 

template<class T> 
std::function<bool(T, T)> GetOperator(const std::string& op) 
{ 
    if (op == "!=") 
     return std::not_equal_to<T>(); 
    else if (op == ">") 
     return std::greater<T>(); 
    else if (op == "<") 
     return std::less<T>(); 
    else if (op == ">=") 
     return std::greater_equal<T>(); 
    else if (op == "<=") 
     return std::less_equal<T>(); 
    else 
    { 
     return std::equal_to<T>(); 
    } 
} 

int main() 
{ 
    auto op = GetOperator<int>(">"); 
    std::cout << op(1, 2) << '\n'; 
    return 0; 
} 
+0

是的,我知道工作,但問題是,即時通訊嘗試返回推力:: binary_function,而不是從std – gumlym

+0

@gumlym你會得到什麼錯誤。我從來沒有用過推力,但快速看看文檔顯示你的代碼應該工作(除了缺失的大括號)。 –

0

儘管沒有確切的答案,我要去把這些我最終使用的東西放在這裏,以防有人需要類似的東西。

在a。CUH文件

#include <cuda.h> 
#include <cuda_runtime_api.h> 

namespace BinaryFunction 
{ 
    enum class ComparisonOperator 
    { 
     equal_to, 
     not_equal_to, 
     greater, 
     less, 
     greater_equal, 
     less_equal 
    }; 

    enum class BitwiseOperator 
    { 
     bit_and, 
     bit_or 
    }; 

    template<typename T> 
    struct CompareFunction 
    { 
     __host__ __device__ T operator()(const T &lhs, const T &rhs, ComparisonOperator &op) const 
     { 
      switch (op) 
      { 
       case ComparisonOperator::equal_to: 
        return lhs==rhs; 
       case ComparisonOperator::not_equal_to: 
        return lhs!=rhs; 
       case ComparisonOperator::greater: 
        return lhs>rhs; 
       case ComparisonOperator::less: 
        return lhs<rhs; 
       case ComparisonOperator::greater_equal: 
        return lhs>=rhs; 
       case ComparisonOperator::less_equal: 
        return lhs<=rhs; 

      } 
     } 
    }; 

    template<typename T> 
    struct BitwiseFunction 
    { 
     __host__ __device__ T operator()(const T &lhs, const T &rhs, BitwiseOperator &op) const 
     { 
     if (op==BitwiseOperator::bit_and) 
      return lhs & rhs; 
     else if (op==BitwiseOperator::bit_or) 
      return lhs | rhs; 
     } 
    }; 
} 

然後使用它是這樣的: 在cpp文件:

BinaryFunction::ComparisonOperator comp_op = BinaryFunction::ComparisonOperator::equal_to; 

BinaryFunction::CompareFunction<int> comp_func; 

然後,在內核中或在正常功能:

int value_a; 
int value_b; 
comp_func(value_a, value_b, comp_op)