2009-08-15 43 views
6

Nói rằng tôi muốn có một hàm C++ để thực hiện số học trên hai đầu vào, đối xử với họ như một loại nhất định:Vượt qua con trỏ tới mẫu-chức năng như đối số chức năng?

giả:

function(var X,var Y,function OP) 
{ 
if(something) 
    return OP<int>(X,Y); 
else if(something else) 
    return OP<double>(X,Y); 
else 
    return OP<string>(X,Y); 
} 

chức năng phù hợp với OP có thể như:

template <class T> add(var X,var Y) 
{ 
return (T)X + (T)Y; //X, Y are of a type with overloaded operators 
} 

Vì vậy, câu hỏi là chữ ký cho chức năng trông như thế nào? Nếu các hàm toán tử không được tạo mẫu, tôi có thể làm điều đó, nhưng tôi bị lẫn lộn với sự phức tạp thêm này.

+1

Xem đối số mẫu tiêu bản. (Và đó không phải là lỗi đánh máy.) – sbi

+0

+1, đó là câu trả lời đúng về cách vượt qua OP. – MSalters

+0

Tôi đã thêm câu trả lời này làm câu trả lời. Tôi hy vọng tôi đã không đặt bất kỳ lỗi ngu ngốc vào nó. – sbi

Trả lời

4

Bạn đang tìm kiếm điều này?

template<class T> T add(T X, T Y) 
{ 
    return X + Y; 
} 

Hoặc bạn đang tìm kiếm thứ gì đó gọi là thêm?

template<class T, class F> 
T Apply(T x, T y, F f) 
{ 
    return f(x, y); 
} 

gọi qua:

int x = Apply(2, 4, add<int>); 
+0

Tôi tin rằng anh ấy muốn chuyển * thêm * ** mà không cần chỉ định * int * làm đối số mẫu. – izogfif

5

Tôi là một chút bối rối ... tại sao loại sự khác biệt trong pseudo-code của bạn?

C++ template cho phép toàn loại trừ trên các mẫu:

template <typename T, typename F> 
T function(T x, T y, F op) { 
    return op(x, y); 
} 

Ở đây, F phù hợp với bất cứ điều gì (đặc biệt là chức năng) có thể được gọi với cú pháp gọi () chức năng và chấp nhận chính xác hai tham số kiểu T (hoặc ngầm chuyển đổi sang nó).

+0

Tôi nghĩ rằng đây là những gì tôi có nghĩa là, đã không nghĩ về một chức năng như là một đối số mẫu. –

+0

Vấn đề duy nhất là F không thể là hàm mẫu với các đối số mẫu không xác định, nó phải là một hàm không phải mẫu, hoặc hàm mẫu với tất cả các kiểu mẫu được chỉ định. – izogfif

+0

@izogfif Bạn cũng có thể chỉ định rõ ràng đối số mẫu. Deducing chúng có thể được thực hiện bằng cách sử dụng lập trình meta mẫu. Nhưng dù sao thì có vẻ như câu trả lời của OP đã được trả lời, không cần phải làm phức tạp thêm nữa. –

0

Tôi không chắc chắn điều này có nghĩa là gì trong câu hỏi của bạn là var. Nó chắc chắn không phải là một từ khóa C++ hợp lệ, vì vậy tôi cho rằng đó là một loại tương tự như boost:any. Ngoài ra, hàm thiếu kiểu kết quả. Tôi đã thêm một số khác là var. Giải pháp của bạn có thể trông giống như sau:

template< template<typename> class Func > 
var function(var X, var Y, Func OP) 
{ 
if(something) 
    return OP<int>(X,Y); 
else if(something else) 
    return OP<double>(X,Y); 
else 
    return OP<string>(X,Y); 
} 

Đối số mẫu hài hước là bản thân mẫu, do đó tên của nó là "đối số mẫu mẫu". Bạn vượt qua tên của một mẫu, không phải là một thể hiện. Nghĩa là, bạn vượt qua std::plus, không std::plus<int>:

return function(a, b, std::plus); 
+0

Không hoạt động trong Visual C++ 2008, Visual C++ 2010 do lỗi biên dịch. – izogfif

+0

@izogfif: Bây giờ hình ảnh, trong một khoảnh khắc, bạn đã cung cấp lỗi trình biên dịch chính xác. Ai đó có thể đã đi cùng, nhìn vào nó, hiểu vấn đề là gì và đăng một giải pháp. Tất nhiên, chúng tôi không muốn điều này, vì vậy nó là tốt, bạn đã không cung cấp đó. – sbi

+0

Điểm tốt. Đây là mã tôi đã cố gắng biên dịch và lỗi được trình biên dịch đưa ra (ở cuối mã): http://pastebin.com/YyhX9ruT – izogfif

5

chức năng mẫu không thể được thông qua như các đối số mẫu. Bạn phải tự suy ra các đối số mẫu cho hàm này trước khi bạn chuyển nó tới một hàm mẫu khác.Ví dụ, bạn có chức năng

T sum(T a, T b) 
{ 
    return a + b; 
} 

Bạn muốn vượt qua nó để callFunc:

template<typename F, typename T> 
T callFunc(T a, T b, F f) 
{ 
    return f(a, b); 
} 

Bạn không thể chỉ đơn giản là viết

int a = callFunc(1, 2, sum); 

Bạn phải viết

int a = callFunc(1, 2, sum<int>); 

Để có thể vượt qua tổng số mà không cần viết int, bạn phải viết một hàm - cấu trúc hoặc lớp với toán tử() sẽ gọi hàm mẫu của bạn. Sau đó, bạn có thể chuyển functor này làm đối số mẫu. Đây là một ví dụ.

template<class T> 
T sum(T a, T b) 
{ 
    return a + b; 
} 
template<class T> 
struct Summator 
{ 
    T operator()(T a, T b) 
    { 
     return sum<T>(a, b); 
    } 
}; 
template<template<typename> class TFunctor, class T> 
T doSomething(T a, T b) 
{ 
    return TFunctor<T>()(a, b); 
    //Equivalent to this: 
    //TFunctor<T> functor; 
    //return functor(a, b); 
} 


int main() 
{ 
    int n1 = 1; 
    int n2 = 2; 
    int n3 = doSomething<Summator>(n1, n2); //n3 == 3 
    return 0; 
} 
+0

Sự nhầm lẫn này sẽ không xuất hiện ngay từ đầu nếu mọi người sử dụng thuật ngữ chính xác: “ chức năng mẫu "không tồn tại, chúng là" mẫu chức năng ". Tức là, trong ví dụ của bạn 'callFunc (1, 2, sum);' bạn ** không ** chuyển một hàm tới 'callFunc', bạn đang truyền một * template * tới nó (và như ví dụ của bạn cho bạn thấy * có thể * chuyển mẫu dưới dạng đối số mẫu, nhưng chỉ * mẫu * lớp *, không phải * mẫu * chức năng). –

+0

Hm .. Không nghĩ về nó theo cách này. Tôi tin rằng câu hỏi ban đầu nên là "Làm thế nào để vượt qua mẫu chức năng như đối số mẫu chức năng" sau đó, phải không? – izogfif

+0

Vì vậy, làm thế nào bạn sẽ làm cho giải pháp này làm việc nếu tổng là một thành viên không tĩnh của một lớp học? –

1

Tôi sử dụng lambdas cho việc này.

auto add = [](const auto& lhs, const auto& rhs) { 
    static_assert(std::is_arithmetic<typename std::decay<decltype(lhs)>::type>::value, 
      "Needs to be arithmetic."); 
    static_assert(std::is_arithmetic<typename std::decay<decltype(rhs)>::type>::value, 
      "Needs to be arithmetic."); 
    return lhs + rhs; 
}; 

template<typename LHS, typename RHS, typename FUNC 
    , typename OUT = typename std::result_of<FUNC(LHS, RHS)>::type> 
constexpr OUT do_arithmetic(LHS lhs, RHS rhs, FUNC func) { 
    return func(lhs, rhs); 
} 

constexpr auto t = do_arithmetic(40, 2, add); 
static_assert(t == 42, "Wrong answer!"); 
static_assert(std::is_same<std::decay<decltype(t)>::type, int>::value, 
     "Should be int."); 
Các vấn đề liên quan