C
cgv
Hi,
I want to distinguish between an int parameter to a template function
depending on whether its value is known at compile time or not. For the
compile time version I want to call the function with the syntax
func<5>();
and for the dynamic version with
func(5);
This can be simply achieved by function overloading through the two function
declarations:
template <int i> void func() { ... }
void func(int i) {... }
The same thing I want to combine with argument dependent lookup (ADL).
Therefore the functions are declared inside a namespace for example "test"
and both get an argument of a templated typename T:
namespace test {
template <int i, typename T> void func(const T&) {...}
template <typename T> void func(int i, const T&) {...}
}
If we now declare a struct A inside the same namespace:
namespace test {
struct A { ... };
}
ADL should allow us to use func on an instance of A in the main function
without specifying the namespace test:
void main(int,char**) {
test::A a;
func<2>(a); // error under visual studio 8 (.Net 2005)
func(2,a); // this is fine
}
In this code the ADL does not work for the compile time version, where the
int is passed as template argument. Now my questions:
1. Is this a bug of the Visual Studio 8 compiler or is this use of ADL not
intended by the standard?
2. Has anyone a good idea of circumvent this problem without messing up the
notation too much?
In order to let you try this out on other compilers here is a complete
example:
#include <iostream>
namespace test
{
template <int i, typename T>
void func_a(const T& t)
{
std::cout << "called func with t = " << t << " and i = " << i <<
std::endl;
}
template <typename T>
void func_b(int i, const T& t)
{
std::cout << "called func with t = " << t << " and i = " << i <<
std::endl;
}
struct A
{
int i;
A(int _i) : i(_i) {}
friend std:
stream& operator << (std:
stream& os, const A& a)
{
return os << a.i;
}
};
}
void main(int, char**)
{
test::A a(3);
func_a<1>(a); // error
func_a<1,test::A>(a); // error
test::func_a<1>(a); // this is fine but does not help
func_b(1, a); // this works perfect
}
I want to distinguish between an int parameter to a template function
depending on whether its value is known at compile time or not. For the
compile time version I want to call the function with the syntax
func<5>();
and for the dynamic version with
func(5);
This can be simply achieved by function overloading through the two function
declarations:
template <int i> void func() { ... }
void func(int i) {... }
The same thing I want to combine with argument dependent lookup (ADL).
Therefore the functions are declared inside a namespace for example "test"
and both get an argument of a templated typename T:
namespace test {
template <int i, typename T> void func(const T&) {...}
template <typename T> void func(int i, const T&) {...}
}
If we now declare a struct A inside the same namespace:
namespace test {
struct A { ... };
}
ADL should allow us to use func on an instance of A in the main function
without specifying the namespace test:
void main(int,char**) {
test::A a;
func<2>(a); // error under visual studio 8 (.Net 2005)
func(2,a); // this is fine
}
In this code the ADL does not work for the compile time version, where the
int is passed as template argument. Now my questions:
1. Is this a bug of the Visual Studio 8 compiler or is this use of ADL not
intended by the standard?
2. Has anyone a good idea of circumvent this problem without messing up the
notation too much?
In order to let you try this out on other compilers here is a complete
example:
#include <iostream>
namespace test
{
template <int i, typename T>
void func_a(const T& t)
{
std::cout << "called func with t = " << t << " and i = " << i <<
std::endl;
}
template <typename T>
void func_b(int i, const T& t)
{
std::cout << "called func with t = " << t << " and i = " << i <<
std::endl;
}
struct A
{
int i;
A(int _i) : i(_i) {}
friend std:
{
return os << a.i;
}
};
}
void main(int, char**)
{
test::A a(3);
func_a<1>(a); // error
func_a<1,test::A>(a); // error
test::func_a<1>(a); // this is fine but does not help
func_b(1, a); // this works perfect
}