I want to create an alias to CPPUNIT_ASSERT_EQUAL_MESSAGE(string message, T expected, T actual). I tried:
template<class T> void (&_assert)(string, T, T) = &CPPUNIT_ASSERT_EQUAL_MESSAGE;
Not sure if its right at all, but I am getting errors like
Error 1 error C2530: '_assert' : references must be initialized h:\dropbox\sch\cs3202\code\test\testqueryevaluator\testgetcandidatelist.h 22
Error 2 error C2998: 'void (__cdecl &__cdecl _assert)(std::string,T,T)' : cannot be a template definition h:\dropbox\sch\cs3202\code\test\testqueryevaluator\testgetcandidatelist.h 22
Whats the right syntax?
Just create a forwarding function:
template<class T>
inline void _assert(const string& message, T expected, T actual)
{ CPPUNIT_ASSERT_EQUAL_MESSAGE(message, expected, actual); }
Simple put, there is no right syntax, because, as phoeagon noted, that is a macro, no function:
See the reference
CPPUNIT_ASSERT_EQUAL_MESSAGE is a macro and not a function, and so you can either "wrap" it with an actual definition of an inline function (as a previous answer suggested) or simply #define an alias macro:
#define _assert CPPUNIT_ASSERT_EQUAL_MESSAGE
Of the two, I would choose the wrapper function method so it could be declared in a namespace and to avoid naming conflicts.
Related
I have a template function in the style:
template <int Exponent> DERIVED_TYPE pow(TYPE const x);
This function is defined inline in a template struct as a friend function:
template <ARGUMENTS>
struct unit {
typedef unit<ARGUMENTS> type;
....
template <int Exponent>
friend constexpr unit_pow_t<type, Exponent> pow(type const x) { ... }
};
This is because taking a value with a unit to a power has to change the unit along with the value.
When I try to use it omitting the Exponent, I can see the candidates the compiler considers for matching:
src/model/Tool.cpp:113:3: error: no matching function for call to 'pow'
pow(1._m);
^~~
src/model/../units/Units.hpp:2266:46: note: candidate template ignored: couldn't infer template argument 'Exponent'
friend constexpr unit_pow_t<type, Exponent> pow(type const x) {
^
/usr/include/math.h:255:8: note: candidate function not viable: requires 2 arguments, but 1 was provided
double pow(double, double);
^
So far things are as expected, the template is seen, but of course the Exponent needs to be specified. When I do however something unexpected happens:
src/model/Tool.cpp:113:6: error: comparison between pointer and integer ('double (*)(double, double)' and 'int')
pow<3>(1._m);
~~~^~
The compiler sees pow as the address of "double pow(double, double)" and interprets <3 as the intent to compare the function pointer with the integer. The problem occurs with clang 3.4, 3.6 and GCC 5.2.
My question is, how do I convince the compiler that <3> is a template argument list?
UPDATE
I finally managed to create a minimal example, sorry for the incomplete question:
template <int Exp>
struct metre {
double value;
template <int Exponent>
friend constexpr metre<Exp * Exponent> pow(metre<Exp> const x) {
return {0};
}
};
int main() {
pow<2>(metre<1>{1});
return 0;
};
It seems it is not seeing pow:
targs.cpp:11:2: error: use of undeclared identifier 'pow'
pow<2>(metre<1>{1});
^
If I include cmath I have the same diagnostics as before:
targs.cpp:13:5: error: comparison between pointer and integer ('double (*)(double, double)' and 'int')
pow<2>(metre<1>{1});
~~~^~
1 error generated.
So the presence of "double pow(double, double)" just masks the issue that the template is not seen. The question then is, why is pow<>() not seen by the compiler?
There is no need (and no logic) for the friend template. Use a free function:
template <int Exp>
struct metre {
double value;
};
template<int B, int A>
constexpr auto pow(metre<A> const x) -> metre<A*B>
{
return metre<A*B>{x.value};
}
int main() {
metre<2> result = pow<2>(metre<1>{1});
return 0;
};
Live demo on coliru.
This is the template friends problem, with two quirks: the name of the function being pow; and the template friend has its own template parameter!
As a rule of thumb, be on guard whenever you use friend inside a class template.
To get the easier problem out of the way first: as posted, in the MCVE, the class definition of metre doesn't cause a name pow to be declared (this will be explained later). Your error message is coming because there is in fact a visible declaration of a name pow: it's in the C standard library header math.h. The "pointer" in the error message is a function pointer to this function.
It's a good idea to not name your function the same as a function in the C standard library. Those may be defined as preprocessor macros anyway, causing further trouble.
For the rest of this post I will assume the MCVE has pow swapped out for pok , to avoid this wrinkle. Then a sane error message is generated:
po.cc:13:5: error: 'pok' was not declared in this scope
pok<2>(metre<1>{1});
^
Moving onto the main issue now.
The basic version of the problem is discussed here. The issue is that declaring a friend function inside a class template does NOT make the friend function also be a template function with the same parameter as the class template.
In fact, what happens is that for each instantiation of the class template, the friend declaration declares a non-template friend for that instantiation.
To see this in action, in your MCVE, add the line metre<1> m; as the first line of main. This instantiates metre<1>, which causes template<int Exponent> pok(metre<1>) to exist, and so the compiler recognizes pok on the next line!
In fact, any particular instantiation works, not just metre<1>, because this at least allows name lookup of pok to succeed, and then by the time overload resolution occurs (two-phase lookup!) , the argument metre<1> has caused metre<1> to be instantiated.
Closing note: I'm not entirely sure the above explanation is correct - template friends are pretty complicated. Maybe it'll turn out that actually pok is supposed to be declared and the compiler is bugged. But I concur with rubenvb's suggestion that it is best to avoid this situation entirely by not using a friend.
With the help of the previous answers I figured out a workaround.
The problem is that the friends are defined (more or less as expected) but not known outside of class/struct scope. So the compiler does not find them.
The solution is to put a declaration outside of the struct:
template <int Exp>
struct metre {
double value;
template <int Exponent>
friend constexpr metre<Exp * Exponent> pow(metre<Exp> const x) {
return {23};
}
};
template <class> void pow(); // <== HERE BE DRAGONS
int main() {
static_assert(pow<2>(metre<1>{1}).value == 23, "foobar");
return 0;
};
Note that it is not necessary to provide a matching declaration. Any template declaration for a function with the right name seems to allow the compiler to discover the friend template function.
What I'm trying to do: I've got a template object incoming which, as part of an interface, should have a "process" function defined with a number of arguments (I don't know how many) some of which are template arguments.
I.e.
struct A { static void process(int a); };
struct B { template <typename B0> static void process(int a, B0 b0); };
are both valid handlers to receive. So now I need to detect a signature for a handler: static-typed parameters and a number of template parameters.
To do so, I'm using a number of template magic hacks which may be narrowed down to the problematic part - detecting a number of template args (or just retrieving a templated signature).
The way I'm trying to find out the required info is by checking for a explicitly specialized signature using the method described in Is it possible to write a template to check for a function's existence?
struct _D;
template <typename T>
struct get_template_args_count
{
private:
template <int count> struct R { enum { value = count }; };
template <typename C>
static R<0> retrieve(decltype(&C::process));
template <typename C>
static R<1> retrieve(decltype(&C::template process<_D>));
template <typename C>
static R<-1> retrieve(...);
public:
typedef decltype(retrieve<T>(nullptr)) Result;
enum { value = Result::value };
};
int main(int argc, char* argv[])
{
std::cout
<< "A::process " << get_template_args_count<A>::value << "\n"
<< "B::process " << get_template_args_count<B>::value << "\n";
std::cin.get();
return 0;
}
With clang (built with msvc2013 or linux version, built with gcc-4.9.2) it compiles and outputs:
A::process 0
B::process 1
With msvc2012 it compiles too, but outputs:
A::process 0
B::process -1
When cornered in by commenting out the fallback case (the one with (...)) msvc2012 freaks out:
main.cpp(28): error C2893: Failed to specialize function template 'get_template_args_count<T>::R<count> get_template_args_count<T>::retrieve(unknown)'
with [ T=B, count=1 ]
With the following template arguments: 'B'
v:\test\test\test\main.cpp(63) : see reference to class template instantiation 'get_template_args_count<T>' being compiled
with [ T=B ]
main.cpp(28): error C2893: Failed to specialize function template 'get_template_args_count<T>::R<count> get_template_args_count<T>::retrieve(unknown)'
with [ T=B, count=0 ]
With the following template arguments: 'B'
main.cpp(29): error C2825: 'get_template_args_count<T>::Result': must be a class or namespace when followed by '::'
with [ T=B ]
main.cpp(29): error C2039: 'value' : is not a member of '`global namespace''
main.cpp(29): error C2275: 'get_template_args_count<T>::Result' : illegal use of this type as an expression
with [ T=B ]
main.cpp(29): error C2146: syntax error : missing '}' before identifier 'value'
main.cpp(29): error C2143: syntax error : missing ';' before '}'
main.cpp(29): error C2365: 'value' : redefinition; previous definition was 'enumerator'
main.cpp(29) : see declaration of 'value'
(the log is slightly reformatted to take less lines)
I've also tried to use different techniques described in comments of the question above (using char[sizeof], using typeof and moving the check into return type), to no avail - it either produce the same results or falls apart with even weirder errors (including "unexpected end-of-file" with no obvious reason).
I've also checked out a similar question Deduce variadic args and return type from functor template parameter (MSVC-specific) with another technique (comparing prototypes via SFINAE), but I can't see how to use it when I don't know exact signature (i.e. I don't know a number and types of static parameters). I may brute-force them for a specific task at hand, of course, but...
So I've got two questions:
Why it should be always so hard with MSVC?.. Ok, that's a rhetoric one, no answer is needed.
Am I abusing some kindness of clang/gcc and actually MSVC is doing the right thing by throwing meaningless errors at my face? Are there any workarounds or right ways to do this, other than brute-forcing all possible static/template parameters combinations and comparing them using a full signature prototype?
The problem here is that MSVC refuses to extract the type of &C::template process<_D> to use in overload resolution (Note the absence of any meaningful error message). It appears that it considers the instanciated function to be an overload-set of only one function; probably an implementation goof.
You can force it to convert the overload-set to a function pointer type by feeding it into a function parameter:
template<typename T>
T* fn_id(T* func) {
return nullptr;
}
Once T has been flattened into a function type, you can use it into decltype.
template <typename C>
static R<1> retrieve(decltype(fn_id(&C::template process<_D>)));
With this hack I get the same output as you had with clang.
The following minimal code compiles and links fine in GNU C++:
#include <iostream>
// Simple function
template<class T>
void foo(T a,void* = 0) {
std::cout << a << std::endl;
}
// A distpatching class
template<
class T,
void (*Function)(T,void*)
>
class kernel {
public:
// Function dispatcher
template<class M>
inline static void apply(M t) {
Function(t,0);
}
};
int main()
{
kernel<int,foo>::apply(5);
//foo(5,0);
}
but with Visual Studio 2008 it produces the error
error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""void __cdecl foo<int>(int,void *)" (??$foo#H##YAXHPAX#Z)" in Funktion ""public: static void __cdecl kernel<int,&void __cdecl foo<int>(int,void *)>::apply<int>(int)" (??$apply#H#?$kernel#H$1??$foo#H##YAXHPAX#Z##SAXH#Z)".
Obviously the whole function implementation is there, but it seems that the compiler throws away the implementation of the foo function. If the commented line is activated then the linker finds the symbol.
I think (as g++ compiles it fine) this is valid code, so I suppose there is some bug in VS 2008, or am I doing something wrong here? Does anyone knows a workaround/solution for this? The final code has to work with Visual Studio 2008 and in the real code it is not possible to guess all the template type combinations (i.e. I cannot explicitly instantiate the functions for all available types: here just T, in the real code, up to 5 template parameters with arbitrary classes are used).
Original question
In answer to the original question; is this a bug, are there workarounds?
Yes, it looks like you have found a bug in VS2008, I've tested it with VS2008 and VS2013.2 with the same linker error. I would encourage you to file a bug report with Microsoft. Are there workarounds, I believe there may be.
As you noted, it looks like the compiler "looses" the implicit instantiation of the template foo<int> somewhere between the decay to void (*Function)(T,void*) and when it is needed at link time. Having played with the code a little, I think it may involve the apply(M) template and Microsoft's template parsing techniques; since, if apply just takes an int as its argument apply(int) (i.e. no template) it seems happy to compile and link it.
To workaround this, the code can be changed as follows (adding the default constructor and changing the apply call to be made from an instance of kernel). I know this may look ugly; but it works around the issue and may help you work around the issue in your project.
#include <iostream>
// Simple function
template<class T>
void foo(T a,void* = 0) {
std::cout << a << std::endl;
}
// A distpatching class
template<class T,
void(*Function)(T,void*)>
class kernel {
void (*dummy)(T,void*);
public:
kernel() : dummy(Function) {
// "Force" an implicit instantiation...
// dummy can be either a member variable or declared in
// in the constructor here. It exists only to "force"
// the implicit instantiation.
// Alternative...
//void* dummy = (void*)Function;
//(void)dummy; // silence "unused" warnings
}
// Function dispatcher
template<class M>
inline static void apply(M t) {
Function(t,0);
}
};
int main()
{
kernel<int,foo>().apply(5);
// The kernel temporary instantiation is only needed once for the
// following line to link as well.
//kernel<int,foo>::apply(5);
}
The code compiles and links with VS2008, VS2013 and gcc.
How does the code work with modern compilers?
With reference to the comments posted on the original question; why or how does this work with a modern compiler? It centres around two C++ facilities.
Function pointer decay
With any additional rules if applicable (e.g templates)
Implicit function template instantiation
When supplying foo as an argument for void(*Function)(T,void*), a decay takes place and a pointer is used, as if &foo had been used.
Function-to-pointer conversion 4.3
1 An lvalue of function type T can be converted to a prvalue of type “pointer to T.” The result is a pointer to the function
Function-to-pointer conversions reference section 13.4 for additional rules when there are possible overloaded functions. Note the details on the usage of & and the case where the function is a template (emphasis mine).
Address of overloaded function 13.4
1 A function template name is considered to name a set of overloaded functions... The overloaded function name can be preceded by the & operator.
2 If the name is a function template, template argument deduction is done (14.8.2.2), and if the argument deduction succeeds, the resulting template argument list is used to generate a single function template specialization, which is added to the set of overloaded functions considered.
Given the pointer and the compiler's deduction of the type required T for the function foo being int in this case. The compiler then generates the code for the function void foo(int,void*) and then this is used during linking.
Implicit instantiation 14.7.1
3 Unless a function template specialization has been explicitly instantiated or explicitly specialized, the function template specialization is implicitly instantiated when the specialization is referenced in a context that requires a function definition to exist.
Quotes taken from C++ WD n3797
function definition
const circularLinkedList<Tp>& operator=(const circularLinkedList<Tp>& otherList);
lines that cause the error, error message refers to line 327, which starts at nodeType....
template <class Tp>
nodeType<Tp>* circularLinkedList<Tp>&::operator=(const circularLinkedList<Tp>& otherList)
And the error messages from the gcc compiler are:
circularLinkedList.h:327: error: invalid declarator before â&â token
circularLinkedList.h:327: error: expected initializer before â&â token
I assume that I have made some sort of syntax error in in defining this method somewhere. How would I have to go about fixing it? Thanks.
Can you post a little bit more code for us? Can you explain what nodeType is?
The following looks like a function definition:
template <class Tp>
nodeType<Tp>* circularLinkedList<Tp>&::operator=(const circularLinkedList<Tp>& otherList)
However, for one thing, the declaration says it returns a const circularLinkedList<Tp>&.
Also, you don't want to have the & before the ::. It needs to be the type's name, not a pointer or reference to a variable of that type. If you want that behavior you need to use a proxy class.
So it should be something like:
template <class Tp>
const circularLinkedList<Tp>& circularLinkedList<Tp>::operator=(const circularLinkedList<Tp>& other)
Which should almost invariably end with return *this;
In the first code block, you show the method declaration, not the function definition.
In the second code block, you show the header of the method definition.
Method Declaration:
Returns const circularLinkedList<Tp>&
Method Definition:
Returns nodeType<Tp>*.
You are not defining the method you declared.
You are defining some method you have not declared.
The header of the definition should be:
const circularLinkedList<Tp>& circularLinkedList<Tp>::operator=(const circularLinkedList<Tp>& otherList)
I'm having difficulty getting the correct syntax for a template specialisation which accepts a regular c-style string. For example
namespace RubyUtils
{
template<class T> VALUE toValue(const T& v);
};
template<> VALUE toValue(char const* & v)
{
return toValue<string>(v);
}
and then at the call site
return RubyUtils::toValue("Life the universe and everything");
gives an error
unresolved external symbol "unsigned long __cdecl RubyUtils::toValue<char const [33]>(char const (&)[33])"
how should I structure the specialisation to enable passing in c-style strings?
UPDATE: Fixed the template specialisation to have correct syntax template => template<>
I think that the problem you're encountering is probably related to the fact that you've defined two templates - one inside of the namespace, and one out. The error is likely due to this confusion.
But more importantly, as a general rule, you do not want to specialize function templates. Template specialization for function has lots of funky rules associated with it that almost universally result in the wrong thing getting called. Rather, just use regular function overloading:
namespace RubyUtils
{
template<class T> VALUE toValue(const T& v);
VALUE toValue(char const* v)
{
return toValue<string>(v);
}
};
The way function overloading works, calling the toValue function with a C-style string will cause the non-template toValue to get selected ahead of the toValue template, essentially doing the specialization for you. More generally, with function templates, prefer using overloading to specialization. It's just safer.