2013-06-27 6 views
0

У меня есть объектприсвоение локальной переменной глобальной переменной в C++

template <class FLOAT> 
struct Cstruct { 
     Struct1<FLOAT> _var1; 
     Struct2<FLOAT> _var2; 
     Cstruct(){}; 
     Cstruct(Struct1 var1,Struct2 var2):_var1(var1),_var2(var2){}; 
}; 

FLOAT может быть "двойной" или "INT". Struct1 и Struct2 также шаблонизируются с помощью FLOAT.

теперь я также глобальная переменная, объявленная

Cstruct<double> globalObj_d;Cstruct<int> globalObj_i; 

внутри основной() У меня есть

main(){ 
    // some code 
    if double then call func<double>(); 
    if int then call func<int>();   

} 

и внутри Шаблонные FUNC() У меня есть

template<class FLOAT> void func(){ 
// some code 
Struct1<FLOAT> var1; 
Struct2<FLOAT> var2; 
Cstruct<FLOAT> localObj(var1,var2); 
// now i want to assign "localObj" to the global object "globalObj_d" 
if double then 
    globalObj_d = localObj; 
if int then 
    globalObj_i = localObj; 
} 

и я получаю ошибка, указанная

error C2679: binary '=' : no operator found which takes a right-hand operand of type 'Cstruct<FLOAT> 

делает это означает, что я должен явно написать «operator =» внутри Cstruct? мое недооценивание шаблонизированного и глобального объекта, похоже, является некорректным. любая помощь будет очень признательна.

+4

Пожалуйста, скажите мне, что это делает в C++: 'if double then'. Кажется, вы говорите на другом языке. – ondrejdee

+0

Если строки операторов не являются C++, я просто дал псевдокод, чтобы объяснить проблему. Я просто создал пример проблемы, чтобы продемонстрировать проблему, с которой я столкнулся. – user1612986

+0

Я получаю ошибку C2955: «Struct1»: использование шаблона класса требует, чтобы список аргументов шаблона на втором конструкторе CStruct - это именно ваш код? – doctorlove

ответ

0

В этом случае вам может понадобиться. См. rule of three. Компилятор предоставит вам один вариант, если это возможно. Вы не указали нам определения Struct1<FLOAT> или Struct2<FLOAT>. Если он не может генерировать присваивания для них, он не может генерировать один для CStruct.

Пока вы там, избегайте leading underscores на имена переменных.

+0

не с ++ генерирует назначения по умолчанию? – user1612986

+0

@ user1612986: В этом случае, если что-то не отображается в OP. –

+0

Он делает, если может, но мы не знаем, может ли это быть, потому что мы не можем видеть Struct1 или Struct2. – doctorlove

0

Использование psudocode в вашем вопросе затрудняет понимание. Поэтому позвольте мне попытаться сварить это немного в реальном коде. Похоже, что то, что вы пытаетесь сделать, - это, по сути, что-то в этом направлении:

template <typename VAL> 
class Foo 
{ 
public: 
    VAL mVal; 
}; 

int main() 
{ 
    Foo <int> global_i; 
    Foo <double> global_d; 

    Foo <double> local; 

    // ... 
    if (/*someConditional*/) 
    global_i = local; // <== LINE 1 
    else 
    global_d = local; // <== LINE 2 
} 

Это не сработает. Обратите внимание, что хотя во время выполнения выполняется только один из LINE1 или LINE2, они оба скомпилированы во время компиляции. Первый из них пытается присвоить Foo<int> к Foo<double>, но типы не совместимы во многом таким же образом, что они также не совместимы:

class Gee 
{ 
}; 

class Whiz 
{ 
}; 

int main() 
{ 
    Gee g; 
    Whiz w; 

    Gee local; 
    local = w; // <<< INCOMPATIBLE TYPES 
} 

Для того, чтобы сделать эту работу, вам нужно будет либо обеспечить некоторый вид оператора преобразования на Foo преобразовать в другой тип Foo, например:

template <typename VAL> 
class Foo 
{ 
public: 
    template <typename OTHER> operator Foo <OTHER>() const 
    { 
    Foo <OTHER> ret; 
    // ... 
    return ret; 
    } 
}; 

... или, возможно, предоставить две отдельные функции, чтобы сделать задания; один для Foo<int>, а другой для Foo<double>.

+0

Я прочитал if-часть как находящуюся в шаблоне, поэтому локальная имеет тип typename FLOAT, но псевдокод делает это трудно следовать – doctorlove

0

Первый: если тип может быть либо с плавающей точкой, либо с целым числом, не назовите его «FLOAT». Вы можете использовать стандартный T или, возможно, что-то вроде Number, но определенно избегайте FLOAT.

Что касается реального вопроса (или моей догадки по реальному вопросу): почти в любое время, когда вы думаете с точки зрения if (type == X) или switch (type) вид кода (по крайней мере, на C++), вы делаете фундаментальную ошибку - вы может, вероятно, удастся сделать это, если вы хотите достаточно плохо, , но это не так, как C++ предназначен для работы.

В этом случае существует довольно простой способ избежать этого: создать другой шаблон. В частности, вы можете перегрузить несколько шаблонов функций, один для каждого глобальных вы хотите поддержать:

#include <string> 
#include <iostream> 

int i_global; 
double d_global; 

template <class T> 
void assign(T in) { 
    // this function should never be called. 
    assert(false); 
} 

template<> 
void assign<int>(int in) { 
    i_global = in; 
} 

template<> 
void assign<double>(double in) { 
    d_global = in; 
} 

// for the moment, func(input) will just call assign(input): 
template <class T> 
void func(T input) { 
    assign<T>(input); 
} 

int main(int argc, char **argv) { 
    if (argc != 2) { 
     std::cerr << "Usage: trash <number>\n"; 
     return EXIT_FAILURE; 
    } 

    std::string in(argv[1]); 

    // see if the input contains a decimal point, and act accordingly: 
    if (in.find('.') != std::string::npos) 
     func(std::stod(in)); 
    else 
     func(std::stoi(in)); 

    // show the results -- the values of the globals: 
    std::cout << "Result:\ndouble: " << d_global << "\nint: " << i_global << "\n"; 
    return 0; 
} 

я получаю результат я бы надеяться - если я ввожу что-то вроде 1.5 он получает, присвоенную двойной; если я введу что-то вроде 123, он будет присвоен int.