Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.
7956 Discussions

C++ templates program compiles on linux but not on windows

bungeetux
Beginner
655 Views

Hello,

the following example code uses templates and user defined conversion. It compiles and run correctly on linux using Intel Composer XE 2013 :

    template <typename TYPE>
    class Adult {
    public :
    	Adult(TYPE years): age(years) {};

    	TYPE getAge() const {
    		return age;
    	}

    private :
    	TYPE age;
    };

    template <typename TYPE>
    class Child {
    public :
    	Child(TYPE years): age(years) {};

    	TYPE getAge() const {
    		return age;
    	}

    private :
    	TYPE age;
    };

	template <typename TYPE, template <typename T> class PERSON=Child >
    class Human: public PERSON<TYPE> {
    public:
    	Human(TYPE years): PERSON<TYPE>(years){};

        operator Human<TYPE, Child>() const {
		    Human<TYPE, Child> res(this->getAge());
		   return res;
		};

    	TYPE getBirth(TYPE current) const {
    		return (current - this->getAge());
    	}
    };



int test() {

	Human<int,Adult> daddy(30);

	Human<int,Child> toto = daddy; // error : type "Child<TYPE>::Child [with TYPE=int]" is not a class template

	int birthDate = toto.getBirth(2014);

	return birthDate;
}


int main() {
	std::cout << "\n--[Athena," << test() << "] "; std::cout.flush();
}


On Windows, with the same compiler, an error occurs :

test.cpp(43): error : type "Child<TYPE>::Child [with TYPE=int]" is not a class template
test.cpp(43): error : type "Child<TYPE>::Child [with TYPE=int]" is not a class template
            operator Human<TYPE, Child>() const {
            operator Human<TYPE, Child>() const {
                                 ^
            detected during instantiation of class "Human<TYPE, PERSON> [with TYPE=int, PERSON=Child]" at line 59
                                 ^
            detected during instantiation of class "Human<TYPE, PERSON> [with TYPE=int, PERSON=Child]" at line 59

 

Is there any restriction on template use on windows ? Or does the compiler need some option enabled ?

 

0 Kudos
1 Solution
Judith_W_Intel
Employee
655 Views

 

Try this (change the code to look like the #ifdef OK in the declaration below):

#ifdef OK
        operator Human<TYPE, ::Child >() const {
#else
        operator Human<TYPE, Child >() const {
#endif

The problem is that on Windows we emulate the first phase name lookup of the Microsoft compiler which on dependent names without qualifications assumes the non type name (the constructor name) instead of the class name. By qualifying the name with the global scope operator you make it clear that you want the class name.

Judy

View solution in original post

0 Kudos
5 Replies
Shenghong_G_Intel
655 Views

Hi bungeetux,

This looks more like a syntax error as expected. As the error suggested, "Child<TYPE>::Child [with TYPE=int]" is NOT a class template, instead, it is a class. Also, even MS compiler will not pass the test case, Intel compiler is compatible with MS compiler on Windows.

A possible workaround is, change "operator Human<TYPE, Child>() const {" to "operator Human<TYPE, PERSON>() const {", PERSON is a class template, not a class. :)

See below test case:

#include <iostream>

template <typename TYPE>
class Child {
public :
	Child(TYPE years): age(years) {};

	TYPE getAge() const {
		return age;
	}

private :
	TYPE age;
};

template <typename TYPE, template <typename T> class PERSON=Child >
class Human: public PERSON<TYPE> {
public:
	Human(TYPE years): PERSON<TYPE>(years){};

	//operator Human<TYPE, Child>() const {		// This will fail with both ICL and CL
	operator Human<TYPE, PERSON>() const {	// This will pass with both ICL and CL
		Human<TYPE, Child> res(this->getAge());
		return res;
	};
};

int main() {
	Human<int,Child> goodman(30);
	std::cout << "Age: " << goodman.getAge() << std::endl;
}

Let me know your ideas.

Thanks,

Shenghong

0 Kudos
bungeetux
Beginner
655 Views

Hi Shenghong,

Thank you for your response.

The purpose of the operator "operator Human<TYPE, Child>() const { ..." is to make a conversion (in fact a cast) from an object of any template Human<TYPE, PERSON> to an object of specific template Human<TYPE, Child>.

Your workaround allow the compilation of operator declaration but doesn't allow to make the cast in test() function at the line "Human<int,Child> toto = daddy;". In this case, the following error is thrown by the compiler :

Error    3    error : no suitable user-defined conversion from "Human<int, Adult>" to "Human<int, Child>" exists

Perhaps, there is another way to do the conversion.

My problem is that this code works well on Linux and my job is just to compile it on windows with less modifications as possible.

Thanks

Bungee

0 Kudos
Judith_W_Intel
Employee
656 Views

 

Try this (change the code to look like the #ifdef OK in the declaration below):

#ifdef OK
        operator Human<TYPE, ::Child >() const {
#else
        operator Human<TYPE, Child >() const {
#endif

The problem is that on Windows we emulate the first phase name lookup of the Microsoft compiler which on dependent names without qualifications assumes the non type name (the constructor name) instead of the class name. By qualifying the name with the global scope operator you make it clear that you want the class name.

Judy

0 Kudos
Shenghong_G_Intel
655 Views

Hi Bungee,

Sorry, I did not notice that. :(

Please try Judy's suggestion, I've verified and it works.

Thanks,

Shenghong

0 Kudos
bungeetux
Beginner
655 Views

Hi Judy,

Thanks a lot, it effectively works.

Bungee

0 Kudos
Reply