Calling specialized function from other specialized one - c++

I have an error
C2910: 'TEMPLATE_TEST::FuncTemplateTest::InnerFunc' : cannot be explicitly specialized,
while compiling the code below. There are two template functions, and both of them are specialized. When I remove the call to InnerFunc in the specialized outer one, everything works normally. So, where is the problem? (I'm using MS VS 2008.)
class FuncTemplateTest {
public:
template<typename T>
const int OuterFunc(const T& key) const;
private:
template<typename T>
const int InnerFunc(const T& key) const;
};
template<typename T>
inline const int FuncTemplateTest::OuterFunc(const T &key) const
{
std::cout<<"Outer template\n";
return InnerFunc(key);
}
template<>
inline const int FuncTemplateTest::OuterFunc<std::string>(const std::string &key) const
{
std::cout<<"Outer special\n" << key << '\n';
InnerFunc(key); //remove this line to compile!!!
return 1;
}
template<typename T>
inline const int FuncTemplateTest::InnerFunc(const T &key) const
{
std::cout << "Inner template\nTemplate key\n";
return 0;
}
template<>
inline const int FuncTemplateTest::InnerFunc<std::string>(const std::string &key) const
{
std::cout << key << '\n';
return 1;
}

I believe the cause of the problem is that you define an explicit specialization for InnerFunc after that particular specialization has already been used in the code for OuterFunc.
If you move the definitions for InnerFunc before the definitions for OuterFunc, you should be fine. (On GCC this indeed solved the problem.)
Separate note: The return type of your functions is const int, which is not incorrect, but also quite useless (const is ignored when fundamental data types are returned by copy).

Related

const char pointer template specialization

I have this piece of code:
template<typename T>
void test(const T& p);
And I wanted to specialize template with const char* to handle string literals. So I added:
template<>
void test(const char* const& p) { std::cout << "test2\n"; }
But it turns out it doesn't work with call:
test("abc");
I know that "abc" is not technically const char pointer so I should write this:
template<size_t N>
void test(const char (&p)[N]) { std::cout << "test3\n"; }
But I don't want to differientiate between string literal and const char*, eg.:
const char* s = "abc";
test(s); test("abc"); // I want it to call the same function
So I found out that if you write "template specialization" (which is actually just overload) like this:
void test(const char* const& p) { std::cout << "test4\n"; }
it works and test("abc") and test(s) calls the same function. Why is that happening? And can I write actual template specialization for const char* and string literals because above feels like a hack - not the big one but still.
You can add another template, like so:
template<typename T>
void test(const T* p);
And then you can do:
template<>
void test(const char* p) { std::cout << "test2\n"; }
However, I don't see anything wrong with just adding a plain-old non-templated function overload to handle the const char * case:
void test(const char* p) { std::cout << "test4\n"; }
In fact, I much prefer it (because otherwise you get a separate instantiation for each different string you pass to test).

function template overloading - ordering

I don't get it. I know function templates are evil, but in this case we have to use it. So this is not the matter. We have an archive that uses a template-operator-function. The specialisation for objects/vale types follows after the template function declaration/definition:
class BaseArchive
{
public:
BaseArchive() {}
virtual ~BaseArchive();
template< typename T >
BaseArchive & operator<<(const T &t)
{
::operator<<(*this, t);
return *this;
}
};
BaseArchive & operator<<(BaseArchive &ar, const int & i)
{
return ar;
}
class StdArchive : public BaseArchive
{
public:
StdArchive();
template< typename T >
StdArchive & operator<<(const T &t)
{
::operator<<(*this, t);
return *this;
}
};
int main()
{
BaseArchive ar;
int i = 7;
ar << i;
}
For this example we get an error:
::operator<< has not been declared
This one can be fixed by a forward declaration of
class BaseArchive;
BaseArchive & operator<<(BaseArchive &ar, const int & i);
class Archive { ...
So far so good. But afterwards some classes define their own ::operator for the archive and thus it hard or even not possible to ensure that the specific operator declaration occurs always before the archive-header-include nor even we want to use an global operator inlcude file.
Any idea how to solve this and/or a explanation why this error occurs? As usual the VS-compiler soesn't care about that, but the minGW (gcc) compiler does...
many thanks
First, function templates aren't evil. Where did you get that idea?
Second, your setup doesn't make sense. Why is the member function template operator << there? It does nothing except forward to a global version, and because it uses explicit qualification, ADL doesn't apply.
Just remove the member function template and rely on ADL to find the correct operator<<.
Why no freestanding operators and forwarding:
#include<iostream>
struct BaseArchive {};
BaseArchive & operator<<(BaseArchive &ar, const int & i)
{
std::cout << "BaseArchive\n";
return ar;
}
struct StdArchive : BaseArchive {};
template< typename T >
StdArchive& operator<<(StdArchive& archive, const T &t)
{
std::cout << "StdArchive\n";
operator << (static_cast<BaseArchive&>(archive), t);
return archive;
}
int main()
{
StdArchive ar;
ar << 7;
}

How do I avoid implicit conversions on non-constructing functions?

How do I avoid implicit casting on non-constructing functions?
I have a function that takes an integer as a parameter,
but that function will also take characters, bools, and longs.
I believe it does this by implicitly casting them.
How can I avoid this so that the function only accepts parameters of a matching type, and will refuse to compile otherwise?
There is a keyword "explicit" but it does not work on non-constructing functions. :\
what do I do?
The following program compiles, although I'd like it not to:
#include <cstdlib>
//the function signature requires an int
void function(int i);
int main(){
int i{5};
function(i); //<- this is acceptable
char c{'a'};
function(c); //<- I would NOT like this to compile
return EXIT_SUCCESS;
}
void function(int i){return;}
*please be sure to point out any misuse of terminology and assumptions
Define function template which matches all other types:
void function(int); // this will be selected for int only
template <class T>
void function(T) = delete; // C++11
This is because non-template functions with direct matching are always considered first. Then the function template with direct match are considered - so never function<int> will be used. But for anything else, like char, function<char> will be used - and this gives your compilation errrors:
void function(int) {}
template <class T>
void function(T) = delete; // C++11
int main() {
function(1);
function(char(1)); // line 12
}
ERRORS:
prog.cpp: In function 'int main()':
prog.cpp:4:6: error: deleted function 'void function(T) [with T = char]'
prog.cpp:12:20: error: used here
This is C++03 way:
// because this ugly code will give you compilation error for all other types
class DeleteOverload
{
private:
DeleteOverload(void*);
};
template <class T>
void function(T a, DeleteOverload = 0);
void function(int a)
{}
You can't directly, because a char automatically gets promoted to int.
You can resort to a trick though: create a function that takes a char as parameter and don't implement it. It will compile, but you'll get a linker error:
void function(int i)
{
}
void function(char i);
//or, in C++11
void function(char i) = delete;
Calling the function with a char parameter will break the build.
See http://ideone.com/2SRdM
Terminology: non-construcing functions? Do you mean a function that is not a constructor?
8 years later (PRE-C++20, see edit):
The most modern solution, if you don't mind template functions -which you may mind-, is to use a templated function with std::enable_if and std::is_same.
Namely:
// Where we want to only take int
template <class T, std::enable_if_t<std::is_same_v<T,int>,bool> = false>
void func(T x) {
}
EDIT (c++20)
I've recently switched to c++20 and I believe that there is a better way. If your team or you don't use c++20, or are not familiar with the new concepts library, do not use this. This is much nicer and the intended method as outlines in the new c++20 standard, and by the writers of the new feature (read a papers written by Bjarne Stroustrup here.
template <class T>
requires std::same_as(T,int)
void func(T x) {
//...
}
Small Edit (different pattern for concepts)
The following is a much better way, because it explains your reason, to have an explicit int. If you are doing this frequently, and would like a good pattern, I would do the following:
template <class T>
concept explicit_int = std::same_as<T,int>;
template <explicit_int T>
void func(T x) {
}
Small edit 2 (the last I promise)
Also a way to accomplish this possibility:
template <class T>
concept explicit_int = std::same_as<T,int>;
void func(explicit_int auto x) {
}
Here's a general solution that causes an error at compile time if function is called with anything but an int
template <typename T>
struct is_int { static const bool value = false; };
template <>
struct is_int<int> { static const bool value = true; };
template <typename T>
void function(T i) {
static_assert(is_int<T>::value, "argument is not int");
return;
}
int main() {
int i = 5;
char c = 'a';
function(i);
//function(c);
return 0;
}
It works by allowing any type for the argument to function but using is_int as a type-level predicate. The generic implementation of is_int has a false value but the explicit specialization for the int type has value true so that the static assert guarantees that the argument has exactly type int otherwise there is a compile error.
Maybe you can use a struct to make the second function private:
#include <cstdlib>
struct NoCast {
static void function(int i);
private:
static void function(char c);
};
int main(){
int i(5);
NoCast::function(i); //<- this is acceptable
char c('a');
NoCast::function(c); //<- Error
return EXIT_SUCCESS;
}
void NoCast::function(int i){return;}
This won't compile:
prog.cpp: In function ‘int main()’:
prog.cpp:7: error: ‘static void NoCast::function(char)’ is private
prog.cpp:16: error: within this context
For C++14 (and I believe C++11), you can disable copy constructors by overloading rvalue-references as well:
Example:
Say you have a base Binding<C> class, where C is either the base Constraint class, or an inherited class. Say you are storing Binding<C> by value in a vector, and you pass a reference to the binding and you wish to ensure that you do not cause an implicit copy.
You may do so by deleting func(Binding<C>&& x) (per PiotrNycz's example) for rvalue-reference specific cases.
Snippet:
template<typename T>
void overload_info(const T& x) {
cout << "overload: " << "const " << name_trait<T>::name() << "&" << endl;
}
template<typename T>
void overload_info(T&& x) {
cout << "overload: " << name_trait<T>::name() << "&&" << endl;
}
template<typename T>
void disable_implicit_copy(T&& x) = delete;
template<typename T>
void disable_implicit_copy(const T& x) {
cout << "[valid] ";
overload_info<T>(x);
}
...
int main() {
Constraint c;
LinearConstraint lc(1);
Binding<Constraint> bc(&c, {});
Binding<LinearConstraint> blc(&lc, {});
CALL(overload_info<Binding<Constraint>>(bc));
CALL(overload_info<Binding<LinearConstraint>>(blc));
CALL(overload_info<Binding<Constraint>>(blc));
CALL(disable_implicit_copy<Binding<Constraint>>(bc));
// // Causes desired error
// CALL(disable_implicit_copy<Binding<Constraint>>(blc));
}
Output:
>>> overload_info(bc)
overload: T&&
>>> overload_info<Binding<Constraint>>(bc)
overload: const Binding<Constraint>&
>>> overload_info<Binding<LinearConstraint>>(blc)
overload: const Binding<LinearConstraint>&
>>> overload_info<Binding<Constraint>>(blc)
implicit copy: Binding<LinearConstraint> -> Binding<Constraint>
overload: Binding<Constraint>&&
>>> disable_implicit_copy<Binding<Constraint>>(bc)
[valid] overload: const Binding<Constraint>&
Error (with clang-3.9 in bazel, when offending line is uncommented):
cpp_quick/prevent_implicit_conversion.cc:116:8: error: call to deleted function 'disable_implicit_copy'
CALL(disable_implicit_copy<Binding<Constraint>>(blc));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Full Source Code: prevent_implicit_conversion.cc
Well, I was going to answer this with the code below, but even though it works with Visual C++, in the sense of producing the desired compilation error, MinGW g++ 4.7.1 accepts it, and invokes the rvalue reference constructor!
I think it must be a compiler bug, but I could be wrong, so – anyone?
Anyway, here's the code, which may turn out to be a standard-compliant solution (or, it may turn out that that's a thinko on my part!):
#include <iostream>
#include <utility> // std::is_same, std::enable_if
using namespace std;
template< class Type >
struct Boxed
{
Type value;
template< class Arg >
Boxed(
Arg const& v,
typename enable_if< is_same< Type, Arg >::value, Arg >::type* = 0
)
: value( v )
{
wcout << "Generic!" << endl;
}
Boxed( Type&& v ): value( move( v ) )
{
wcout << "Rvalue!" << endl;
}
};
void function( Boxed< int > v ) {}
int main()
{
int i = 5;
function( i ); //<- this is acceptable
char c = 'a';
function( c ); //<- I would NOT like this to compile
}
I first tried PiotrNycz's approach (for C++03, which I'm forced to use for a project), then I tried to find a more general approach and came up with this ForcedType<T> template class.
template <typename T>
struct ForcedType {
ForcedType(T v): m_v(v) {}
operator T&() { return m_v; }
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(T2);
T m_v;
};
template <typename T>
struct ForcedType<const T&> {
ForcedType(const T& v): m_v(v) {}
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(const T2&);
const T& m_v;
};
template <typename T>
struct ForcedType<T&> {
ForcedType(T& v): m_v(v) {}
operator T&() { return m_v; }
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(T2&);
T& m_v;
};
If I'm not mistaken, those three specializations should cover all common use cases. I'm not sure if a specialization for rvalue-reference (on C++11 onwards) is actually needed or the by-value one suffices.
One would use it like this, in case of a function with 3 parameters whose 3rd parameter doesn't allow implicit conversions:
function(ParamType1 param1, ParamType2 param2, ForcedType<ParamType3> param3);

Predicate Inheritance compilation error when using inline instantiation

I'm using a test framework (tut) and noticed a lot of repeatability so I started to abstract out the predicate functions i needed. Below is a simplified example.
It works but I was hoping I could all do it in one line. The problem is when i try to instantiate the derived predicate class inline it fails to compile. Any ideas why?
#include <string>
#include <functional>
#include <iostream>
using namespace std;
template <class T>
struct TestPredicate : public binary_function<T,T,bool>
{
virtual bool operator() (const T& expected, const T& data) const = 0;
};
template <class T>
struct IsEqual : public TestPredicate<T>
{
virtual bool operator() (const T& expected, const T& data) const
{
cout << "IsEqual: " << expected << ", " << data << endl;
return data == expected;
}
};
template <class T>
struct IsNotEqual : public TestPredicate<T>
{
virtual bool operator() (const T& expected, const T& data) const
{
cout << "IsNotEqual: " << expected << ", " << data << endl;
return data != expected;
}
};
struct Tester
{
template <class T>
void test( const T& data, const T& expected, TestPredicate<T>& value_condition )
{
if ( value_condition( expected, data ) )
{
cout << "PASSED" << endl;
}
else
{
cout << "FAILED" << endl;
}
}
};
int main()
{
Tester test;
string data("hello");
string expected("hello");
// this doesn't compile with an inline instantiation of IsEqual
//test.test( data, expected, IsEqual<string>() ); // compilation error (see below)
// this works with an explicit instantiation of IsEqual
IsEqual<string> pred;
test.test( data, expected, pred );
return 0;
}
Compilation Output:
test2.cpp: In function ‘int main()’:
test2.cpp:61:48: error: no matching function for call to ‘Tester::test(std::string&, std::string&, IsEqual<std::basic_string<char> >)’
test2.cpp:61:48: note: candidate is:
test2.cpp:40:8: note: void Tester::test(const T&, const T&, TestPredicate<T>&) [with T = std::basic_string<char>]
test2.cpp:40:8: note: no known conversion for argument 3 from ‘IsEqual<std::basic_string<char> >’ to ‘TestPredicate<std::basic_string<char> >&’
Using g++ 4.6.3
In addition to the other answers, you don't really need runtime polymorphism with virtual functions. You could just make the tester take another template parameter:
template<class T, class Pred>
void test( const T& data, const T& expected, Pred value_condition )
Your Tester::test method needs to take a const reference to the predicate to work with both instantiations.
Temporary object are always const, that is way in test.test( data, expected, IsEqual<string>() ); IsEqual<string>() is of type const TestPredicate<T>.
The explanation to why the compiler complains is both simple and... a bit disheartening.
The C++ Standard rules out that a temporary object (such as created by the expression IsEqual<string>()) can be bound to a const reference, in which case its lifetime is extended to that of the reference.
Because Stroustrup feared that binding to non-const references would only be a source of bugs, it is not however allowed. With hindsight, it turns out that the absence of symmetry is often more surprising; VC++ allows binding to non-const references (as an extension). In C++11, the balance is somewhat restored by allowing binding to "reference reference" (&&), though it still leaves a gap...
... and leaves us in the unpleasant situation you find yourself in.
On the web this is may be referred to as the Most important const.

What is the easiest way to make template function code depending on the parameter type

I want to write a template function that checks some Timestamp property (class inherits from Timed) but also has to work for types that do not have a timestamp. The best (and still quite ugly) solution I have found is the following:
class Timed {
protected:
int mTime;
public:
explicit Timed(int time=0): mTime(time){}
int getT() const {return mTime;}
};
template<typename T>
bool checkStale(T const* ptr) const {
return checkStaleImp(ptr, boost::is_base_of<Timed, T>() );
}
template<typename T>
template<bool b>
bool checkStaleImp(T const* ptr, boost::integral_constant<bool, b> const &){
return true;
}
template<typename T>
bool checkStaleImp(T const* ptr, boost::true_type const&){
const int oldest = 42;
return (42 <= ptr->getT());
}
This is three functions for one functionality. Is there an easier way to accomplish this, e.g. use boost::is_base_of or sth. similar in an if condition or boost::enable if to turn the function output into a sort of constant for classes not deriving from Timed. Solutions with virtual functions are unfortunately not an option.
You can do the same thing with two simple overloads and no template machinery:
bool checkStale(void const* ptr){
return true;
}
bool checkStale(Timed const* ptr){
const int oldest = 42;
return (oldest <= ptr->getT());
}
No need for tag dispatching on is_base_of.
I don't think that is quite ugly solution, as you said. However, you can reduce the scope of helper functions if you implement them as static member of local class as:
template<typename T>
bool checkStale(T const* ptr) const
{
struct local
{
static bool checkStaleImp(T const* ptr, boost::false_type const &)
{
return true;
}
static bool checkStaleImp(T const* ptr, boost::true_type const&)
{
const int oldest = 42;
return (42 <= ptr->getT());
}
};
return local::checkStaleImp(ptr, boost::is_base_of<Timed, T>());
}
Now, there is one function exposed for the user, and the actual implementation inside the local class.
By the way, in C++11, you can use std::is_base_of instead of boost's version. Same with std::true_type and std::false_type.
Use enable_if to select between possible overloads. Since the conditions used in the following example are complimentary there will always be exactly one overload available, and therefore no ambiguity
template<typename T>
typename std::enable_if<std::is_base_of<Timed,T>::value,bool>::type
checkStale(T const *ptr) const {
const int oldest = 42;
return oldest <= ptr->getT();
}
template<typename T>
typename std::enable_if<!std::is_base_of<Timed,T>::value,bool>::type
checkStale(T const *ptr) const {
return true;
}