Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ : &(std::cout) as template argument

Why isn't it possible to pass std::cout's address as template argument? Or if it is possible then how?

Here is what I tried:

#include <iostream>

template<std::ostream* stream>
class MyClass
{
public:
    void disp(void)
        { (*stream) << "hello"; }
};

int main(void)
{
    MyClass<&(std::cout)> MyObj;
    MyObj.disp();

    return 0;
}

And the error message I got from clang++ -std=c++11 :

main.cpp:15:11: error: non-type template argument does not refer to any declaration
        MyClass<&(std::cout)> MyObj;
                 ^~~~~~~~~~~
main.cpp:6:24: note: template parameter is declared here
template<std::ostream* stream>
                       ^
1 error generated.

and from g++ -std=c++11 :

main.cpp: In function ‘int main()’:
main.cpp:15:22: error: template argument 1 is invalid
  MyClass<&(std::cout)> MyObj;
                      ^
main.cpp:15:29: error: invalid type in declaration before ‘;’ token
  MyClass<&(std::cout)> MyObj;
                             ^
main.cpp:16:8: error: request for member ‘disp’ in ‘MyObj’, which is of     non-class type ‘int’
  MyObj.disp();
        ^

Any ideas?

like image 767
Gael Lorieul Avatar asked Sep 29 '16 17:09

Gael Lorieul


2 Answers

Before C++17 removed this restriction, the syntactic form of a template argument for a pointer or reference template parameter was restricted. N4140 [temp.arg.nontype]/1.3 says that it must be

expressed (ignoring parentheses) as & id-expression, where the id-expression is the name of an object or function, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference

(std::cout) isn't an id-expression. It's a primary-expression.

The "(ignoring parentheses)" part was added by Core issue 773, and is apparently meant to permit (&i), not &(i).

like image 161
T.C. Avatar answered Sep 30 '22 02:09

T.C.


This fixes your code, omit the parenthesis:

#include <iostream>

template<std::ostream* stream>
class MyClass
{
public:
    void disp(void) { 
        (*stream) << "hello"; 
    }
};

int main(void)
{
    MyClass<&std::cout> MyObj;
    MyObj.disp();

    return 0;
}

Live Demo


A more detailed explanation why can be found here:

Error with address of parenthesized member function

like image 43
πάντα ῥεῖ Avatar answered Sep 30 '22 02:09

πάντα ῥεῖ